1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Make response of route typed

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2022-02-14 08:47:42 +02:00
parent 4b76327489
commit 79587514d8
No known key found for this signature in database
GPG Key ID: 8C6CFB2FFFE8F68A
24 changed files with 92 additions and 89 deletions

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { LensApiRequest, LensApiResult } from "../router";
import type { LensApiRequest, Route } from "../router";
import staticFileRouteInjectable from "../routes/static-file-route.injectable";
import { getDiForUnitTesting } from "../getDiForUnitTesting";
@ -24,14 +24,14 @@ jest.mock("electron", () => ({
}));
describe("Router", () => {
let handleStaticFile: (request: LensApiRequest) => Promise<LensApiResult>;
let handleStaticFileRoute: Route<Buffer>;
beforeEach(async () => {
const di = getDiForUnitTesting({ doGeneralOverrides: true });
await di.runSetups();
handleStaticFile = di.inject(staticFileRouteInjectable).handler;
handleStaticFileRoute = di.inject(staticFileRouteInjectable);
});
it("blocks path traversal attacks", async () => {
@ -48,7 +48,7 @@ describe("Router", () => {
raw: {},
} as LensApiRequest<any>;
await handleStaticFile(request);
await handleStaticFileRoute.handler(request);
expect(response.statusCode).toEqual(404);
});
@ -73,7 +73,7 @@ describe("Router", () => {
raw: { req },
} as LensApiRequest<any>;
await handleStaticFile(request);
await handleStaticFileRoute.handler(request);
expect(response.statusCode).toEqual(200);
});

View File

@ -132,12 +132,12 @@ export const contentTypes: Record<SupportedFileExtension, LensApiResultContentTy
export class Router {
protected router = new Call.Router();
static rootPath = path.resolve(__static);
protected static rootPath = path.resolve(__static);
constructor(routes: Route[]) {
constructor(routes: Route<any>[]) {
routes.forEach(route => {
this.router.add({ method: route.method, path: route.path }, async (request: LensApiRequest) => {
let result: LensApiResult | void;
let result: LensApiResult<any> | void;
try {
result = await route.handler(request);
@ -220,17 +220,17 @@ interface LensApiResultContentType {
respond: (content: any, statusCode: number, response: http.ServerResponse) => void;
}
export interface LensApiResult {
export interface LensApiResult<TResult> {
statusCode?: number;
response?: any;
response?: TResult;
error?: any;
contentType?: LensApiResultContentType;
headers?: { Location: string };
proxy?: httpProxy;
}
export interface Route {
export interface Route<TResponse> {
path: string;
method: "get" | "post" | "put" | "patch" | "delete";
handler: (request: LensApiRequest) => LensApiResult | Promise<LensApiResult>;
handler: (request: LensApiRequest) => LensApiResult<TResponse> | Promise<LensApiResult<TResponse>>;
}

View File

@ -5,7 +5,7 @@
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
import { Route, Router } from "../router";
export const routeInjectionToken = getInjectionToken<Route>({
export const routeInjectionToken = getInjectionToken<Route<any>>({
id: "route-injection-token",
});

View File

@ -4,21 +4,24 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { routeInjectionToken } from "../../../router/router.injectable";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { apiPrefix } from "../../../../common/vars";
import type { RawHelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api";
interface GetChartResponse {
readme: string;
versions: RawHelmChart[];
}
const getChartRouteInjectable = getInjectable({
id: "get-chart-route",
instantiate: () => ({
instantiate: (): Route<GetChartResponse> => ({
method: "get",
path: `${apiPrefix}/v2/charts/{repo}/{chart}`,
handler: async ({
params,
query,
}: LensApiRequest): Promise<LensApiResult> => ({
handler: async ({ params, query }) => ({
response: await helmService.getChart(
params.repo,
params.chart,

View File

@ -4,21 +4,21 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { routeInjectionToken } from "../../../router/router.injectable";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { apiPrefix } from "../../../../common/vars";
const getChartRouteValuesInjectable = getInjectable({
id: "get-chart-route-values",
instantiate: () => ({
instantiate: (): Route<string> => ({
method: "get",
path: `${apiPrefix}/v2/charts/{repo}/{chart}/values`,
handler: async ({
params,
query,
}: LensApiRequest): Promise<LensApiResult> => ({
}) => ({
response: await helmService.getChartValues(
params.repo,
params.chart,

View File

@ -4,19 +4,18 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { routeInjectionToken } from "../../../router/router.injectable";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { apiPrefix } from "../../../../common/vars";
const listChartsRouteInjectable = getInjectable({
id: "list-charts-route",
instantiate: () => ({
instantiate: (): Route<any> => ({
method: "get",
path: `${apiPrefix}/v2/charts`,
// eslint-disable-next-line unused-imports/no-unused-vars-ts
handler: async (request: LensApiRequest): Promise<LensApiResult> => ({
handler: async () => ({
response: await helmService.listCharts(),
}),
}),

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { apiPrefix } from "../../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { routeInjectionToken } from "../../../router/router.injectable";
import { getInjectable } from "@ogre-tools/injectable";
@ -11,11 +11,11 @@ import { getInjectable } from "@ogre-tools/injectable";
const deleteReleaseRouteInjectable = getInjectable({
id: "delete-release-route",
instantiate: () => ({
instantiate: (): Route<string> => ({
method: "delete",
path: `${apiPrefix}/v2/releases/{namespace}/{release}`,
handler: async (request: LensApiRequest): Promise<LensApiResult> => {
handler: async (request) => {
const { cluster, params } = request;
return {

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { apiPrefix } from "../../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { routeInjectionToken } from "../../../router/router.injectable";
import { getInjectable } from "@ogre-tools/injectable";
@ -11,11 +11,11 @@ import { getInjectable } from "@ogre-tools/injectable";
const getReleaseRouteHistoryInjectable = getInjectable({
id: "get-release-history-route",
instantiate: () => ({
instantiate: (): Route<any> => ({
method: "get",
path: `${apiPrefix}/v2/releases/{namespace}/{release}/history`,
handler: async (request: LensApiRequest): Promise<LensApiResult> => {
handler: async (request) => {
const { cluster, params } = request;
return {

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { apiPrefix } from "../../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { routeInjectionToken } from "../../../router/router.injectable";
import { getInjectable } from "@ogre-tools/injectable";
@ -11,11 +11,11 @@ import { getInjectable } from "@ogre-tools/injectable";
const getReleaseRouteInjectable = getInjectable({
id: "get-release-route",
instantiate: () => ({
instantiate: (): Route<any> => ({
method: "get",
path: `${apiPrefix}/v2/releases/{namespace}/{release}`,
handler: async (request: LensApiRequest): Promise<LensApiResult> => {
handler: async (request) => {
const { cluster, params } = request;
return {

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { apiPrefix } from "../../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { routeInjectionToken } from "../../../router/router.injectable";
import { getInjectable } from "@ogre-tools/injectable";
@ -13,11 +13,11 @@ import { contentTypes } from "../../../router";
const getReleaseRouteValuesInjectable = getInjectable({
id: "get-release-values-route",
instantiate: () => ({
instantiate: (): Route<string> => ({
method: "get",
path: `${apiPrefix}/v2/releases/{namespace}/{release}/values`,
handler: async (request: LensApiRequest): Promise<LensApiResult> => {
handler: async (request) => {
const { cluster, params: { namespace, release }, query } = request;
const all = getBoolean(query, "all");

View File

@ -3,19 +3,24 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { apiPrefix } from "../../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { routeInjectionToken } from "../../../router/router.injectable";
import { getInjectable } from "@ogre-tools/injectable";
interface InstallChartResponse {
log: string;
release: { name: string, namespace: string }
}
const installChartRouteInjectable = getInjectable({
id: "install-chart-route",
instantiate: () => ({
instantiate: () : Route<InstallChartResponse> => ({
method: "post",
path: `${apiPrefix}/v2/releases`,
handler: async (request: LensApiRequest): Promise<LensApiResult> => {
handler: async (request) => {
const { payload, cluster } = request;
return {

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { apiPrefix } from "../../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { routeInjectionToken } from "../../../router/router.injectable";
import { getInjectable } from "@ogre-tools/injectable";
@ -11,11 +11,11 @@ import { getInjectable } from "@ogre-tools/injectable";
const listReleasesRouteInjectable = getInjectable({
id: "list-releases-route",
instantiate: () => ({
instantiate: (): Route<Record<string, any>> => ({
method: "get",
path: `${apiPrefix}/v2/releases/{namespace?}`,
handler: async (request: LensApiRequest): Promise<LensApiResult> => {
handler: async (request) => {
const { cluster, params } = request;
return {

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { apiPrefix } from "../../../../common/vars";
import type { LensApiRequest } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { routeInjectionToken } from "../../../router/router.injectable";
import { getInjectable } from "@ogre-tools/injectable";
@ -11,18 +11,17 @@ import { getInjectable } from "@ogre-tools/injectable";
const rollbackReleaseRouteInjectable = getInjectable({
id: "rollback-release-route",
instantiate: () => ({
instantiate: (): Route<void> => ({
method: "put",
path: `${apiPrefix}/v2/releases/{namespace}/{release}/rollback`,
handler: async (request: LensApiRequest): Promise<void> => {
handler: async (request) => {
const { cluster, params, payload } = request;
await helmService.rollback(cluster, params.release, params.namespace, payload.revision);
},
}),
// @ts-ignore
injectionToken: routeInjectionToken,
});

View File

@ -3,15 +3,20 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { apiPrefix } from "../../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../../router";
import type { Route } from "../../../router";
import { helmService } from "../../../helm/helm-service";
import { routeInjectionToken } from "../../../router/router.injectable";
import { getInjectable } from "@ogre-tools/injectable";
interface UpdateReleaseResponse {
log: string;
release: { name: string, namespace: string }
}
const updateReleaseRouteInjectable = getInjectable({
id: "update-release-route",
instantiate: () => ({
instantiate: (): Route<UpdateReleaseResponse> => ({
method: "put",
path: `${apiPrefix}/v2/releases/{namespace}/{release}`,
@ -19,7 +24,7 @@ const updateReleaseRouteInjectable = getInjectable({
cluster,
params,
payload,
}: LensApiRequest): Promise<LensApiResult> => ({
}) => ({
response: await helmService.updateRelease(
cluster,
params.release,

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import { apiPrefix } from "../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../router";
import type { Route } from "../../router";
import { routeInjectionToken } from "../../router/router.injectable";
import type { Cluster } from "../../../common/cluster/cluster";
import { CoreV1Api, V1Secret } from "@kubernetes/client-node";
@ -13,11 +13,11 @@ import { CoreV1Api, V1Secret } from "@kubernetes/client-node";
const getServiceAccountRouteInjectable = getInjectable({
id: "get-service-account-route",
instantiate: () => ({
instantiate: (): Route<ReturnType<typeof generateKubeConfig>> => ({
method: "get",
path: `${apiPrefix}/kubeconfig/service-account/{namespace}/{account}`,
handler: async (request: LensApiRequest): Promise<LensApiResult> => {
handler: async (request) => {
const { params, cluster } = request;
const client = (await cluster.getProxyKubeconfig()).makeApiClient(CoreV1Api);
const secretList = await client.listNamespacedSecret(params.namespace);

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import { apiPrefix } from "../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../router";
import type { LensApiRequest, Route } from "../../router";
import { routeInjectionToken } from "../../router/router.injectable";
import { ClusterMetadataKey, ClusterPrometheusMetadata } from "../../../common/cluster-types";
import logger from "../../logger";
@ -42,7 +42,7 @@ async function loadMetrics(promQueries: string[], cluster: Cluster, prometheusPa
return Promise.all(queries.map(loadMetric));
}
const addMetricsRoute = async ({ cluster, payload, query }: LensApiRequest): Promise<LensApiResult> => {
const addMetricsRoute = async ({ cluster, payload, query }: LensApiRequest) => {
const queryParams: IMetricsQuery = Object.fromEntries(query.entries());
const prometheusMetadata: ClusterPrometheusMetadata = {};
@ -96,7 +96,7 @@ const addMetricsRoute = async ({ cluster, payload, query }: LensApiRequest): Pro
const addMetricsRouteInjectable = getInjectable({
id: "add-metrics-route",
instantiate: () => ({
instantiate: (): Route<any> => ({
method: "post",
path: `${apiPrefix}/metrics`,
handler: addMetricsRoute,

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import { apiPrefix } from "../../../common/vars";
import type { LensApiRequest, LensApiResult } from "../../router";
import type { Route } from "../../router";
import { routeInjectionToken } from "../../router/router.injectable";
import { PrometheusProviderRegistry } from "../../prometheus";
import type { MetricProviderInfo } from "../../../common/k8s-api/endpoints/metrics.api";
@ -13,12 +13,11 @@ import type { MetricProviderInfo } from "../../../common/k8s-api/endpoints/metri
const getMetricProvidersRouteInjectable = getInjectable({
id: "get-metric-providers-route",
instantiate: () => ({
instantiate: (): Route<MetricProviderInfo[]> => ({
method: "get",
path: `${apiPrefix}/metrics/providers`,
// eslint-disable-next-line unused-imports/no-unused-vars-ts
handler: async (request: LensApiRequest) : Promise<LensApiResult> => {
handler: async () => {
const providers: MetricProviderInfo[] = [];
for (const { name, id, isConfigurable } of PrometheusProviderRegistry.getInstance().providers.values()) {

View File

@ -4,11 +4,11 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { routeInjectionToken } from "../../router/router.injectable";
import type { LensApiRequest, LensApiResult } from "../../router";
import type { LensApiRequest, Route } from "../../router";
import { apiPrefix } from "../../../common/vars";
import { PortForward } from "./functionality/port-forward";
const getCurrentPortForward = async (request: LensApiRequest): Promise<LensApiResult> => {
const getCurrentPortForward = async (request: LensApiRequest) => {
const { params, query, cluster } = request;
const { namespace, resourceType, resourceName } = params;
const port = Number(query.get("port"));
@ -25,7 +25,7 @@ const getCurrentPortForward = async (request: LensApiRequest): Promise<LensApiRe
const getCurrentPortForwardRouteInjectable = getInjectable({
id: "get-current-port-forward-route",
instantiate: () => ({
instantiate: (): Route<{ port: number }> => ({
method: "get",
path: `${apiPrefix}/pods/port-forward/{namespace}/{resourceType}/{resourceName}`,
handler: getCurrentPortForward,

View File

@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { routeInjectionToken } from "../../router/router.injectable";
import type { LensApiRequest, LensApiResult } from "../../router";
import type { LensApiRequest, Route } from "../../router";
import { apiPrefix } from "../../../common/vars";
import { PortForward, PortForwardArgs } from "./functionality/port-forward";
import logger from "../../logger";
@ -14,7 +14,7 @@ interface Dependencies {
createPortForward: (pathToKubeConfig: string, args: PortForwardArgs) => PortForward;
}
const startPortForward = ({ createPortForward }: Dependencies) => async (request: LensApiRequest): Promise<LensApiResult> => {
const startPortForward = ({ createPortForward }: Dependencies) => async (request: LensApiRequest) => {
const { params, query, cluster } = request;
const { namespace, resourceType, resourceName } = params;
const port = Number(query.get("port"));
@ -85,7 +85,7 @@ const startPortForward = ({ createPortForward }: Dependencies) => async (request
const startPortForwardRouteInjectable = getInjectable({
id: "start-current-port-forward-route",
instantiate: (di) => ({
instantiate: (di): Route<{ port: number }> => ({
method: "post",
path: `${apiPrefix}/pods/port-forward/{namespace}/{resourceType}/{resourceName}`,
handler: startPortForward({ createPortForward: di.inject(createPortForwardInjectable) }),

View File

@ -4,12 +4,12 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { routeInjectionToken } from "../../router/router.injectable";
import type { LensApiRequest, LensApiResult } from "../../router";
import type { LensApiRequest, Route } from "../../router";
import { apiPrefix } from "../../../common/vars";
import { PortForward } from "./functionality/port-forward";
import logger from "../../logger";
const stopCurrentPortForward = async (request: LensApiRequest): Promise<LensApiResult> => {
const stopCurrentPortForward = async (request: LensApiRequest) => {
const { params, query, cluster } = request;
const { namespace, resourceType, resourceName } = params;
const port = Number(query.get("port"));
@ -39,7 +39,7 @@ const stopCurrentPortForward = async (request: LensApiRequest): Promise<LensApiR
const stopCurrentPortForwardRouteInjectable = getInjectable({
id: "stop-current-port-forward-route",
instantiate: () => ({
instantiate: (): Route<{ status: boolean }> => ({
method: "delete",
path: `${apiPrefix}/pods/port-forward/{namespace}/{resourceType}/{resourceName}`,
handler: stopCurrentPortForward,

View File

@ -4,21 +4,18 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { routeInjectionToken } from "../../router/router.injectable";
import type { LensApiRequest, LensApiResult } from "../../router";
import type { Route } from "../../router";
import { apiPrefix } from "../../../common/vars";
import { ResourceApplier } from "../../resource-applier";
const applyResourceRouteInjectable = getInjectable({
id: "apply-resource-route",
instantiate: () => ({
instantiate: (): Route<string> => ({
method: "post",
path: `${apiPrefix}/stack`,
handler: async ({
cluster,
payload,
}: LensApiRequest): Promise<LensApiResult> => ({
handler: async ({ cluster, payload }) => ({
response: await new ResourceApplier(cluster).apply(payload),
}),
}),

View File

@ -4,21 +4,18 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { routeInjectionToken } from "../../router/router.injectable";
import type { LensApiRequest, LensApiResult } from "../../router";
import type { Route } from "../../router";
import { apiPrefix } from "../../../common/vars";
import { ResourceApplier } from "../../resource-applier";
const patchResourceRouteInjectable = getInjectable({
id: "patch-resource-route",
instantiate: () => ({
instantiate: (): Route<string> => ({
method: "patch",
path: `${apiPrefix}/stack`,
handler: async ({
cluster,
payload,
}: LensApiRequest): Promise<LensApiResult> => ({
handler: async ({ cluster, payload }) => ({
response: await new ResourceApplier(cluster).patch(
payload.name,
payload.kind,

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { LensApiRequest, LensApiResult, SupportedFileExtension, Route } from "../router";
import type { LensApiRequest, SupportedFileExtension, Route } from "../router";
import { contentTypes } from "../router";
import logger from "../logger";
import { routeInjectionToken } from "../router/router.injectable";
@ -19,7 +19,7 @@ interface ProductionDependencies {
const handleStaticFileInProduction =
({ readFile }: ProductionDependencies) =>
async ({ params }: LensApiRequest): Promise<LensApiResult> => {
async ({ params }: LensApiRequest) => {
const staticPath = path.resolve(__static);
let filePath = params.path;
@ -76,7 +76,7 @@ const handleStaticFileInDevelopment =
const staticFileRouteInjectable = getInjectable({
id: "static-file-route",
instantiate: (di): Route => {
instantiate: (di): Route<Buffer> => {
const isDevelopment = di.inject(isDevelopmentInjectable);
return {

View File

@ -3,19 +3,18 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { LensApiRequest, LensApiResult } from "../../router";
import type { Route } from "../../router";
import { routeInjectionToken } from "../../router/router.injectable";
import { getAppVersion } from "../../../common/utils";
const getVersionRouteInjectable = getInjectable({
id: "get-version-route",
instantiate: () => ({
instantiate: (): Route<{ version: string }> => ({
method: "get",
path: `/version`,
// eslint-disable-next-line unused-imports/no-unused-vars-ts
handler: async (request: LensApiRequest): Promise<LensApiResult> => {
handler: async () => {
return { response: { version: getAppVersion() }};
},
}),