Skip to content

Commit

Permalink
add extension, fix spec showing
Browse files Browse the repository at this point in the history
  • Loading branch information
NikhilShahi committed Aug 7, 2022
1 parent 109e619 commit 6c4d333
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 10 deletions.
4 changes: 4 additions & 0 deletions backend/models/openapi-spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BaseEntity, Entity, PrimaryColumn, Column } from "typeorm";
import { SpecExtension } from "../src/enums";

@Entity()
export class OpenApiSpec extends BaseEntity {
Expand All @@ -8,6 +9,9 @@ export class OpenApiSpec extends BaseEntity {
@Column()
spec: string

@Column({ type: "enum", enum: SpecExtension, default: SpecExtension.JSON})
extension: SpecExtension

@Column({ type: "bool", default: false })
isAutoGenerated: boolean
}
42 changes: 40 additions & 2 deletions backend/src/api/spec/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ApiResponseHandler from "../../api-response-handler";
import Error400BadRequest from "../../errors/error-400-bad-request";
import { AppDataSource } from "../../data-source";
import { OpenApiSpec } from "../../../models";
import { SpecExtension } from "../../enums";

export const getSpecListHandler = async (req: Request, res: Response) => {
try {
Expand All @@ -26,6 +27,16 @@ export const uploadNewSpecHandler = async (req: Request, res: Response) => {
?.split(".json")[0]
?.split(".yaml")[0]
?.split(".yml")[0];
let extension = undefined;
if (specFile.mimetype === "application/json") {
extension = SpecExtension.JSON;
} else if (specFile.mimetype === "text/yaml") {
extension = SpecExtension.YAML;
} else {
throw new Error400BadRequest(
"Only .json, .yaml, and .yml format allowed."
);
}
if (!fileName) {
throw new Error400BadRequest("No filename provided.");
}
Expand All @@ -39,7 +50,12 @@ export const uploadNewSpecHandler = async (req: Request, res: Response) => {
const specObject: JSONValue = yaml.load(
specFile.buffer.toString()
) as JSONValue;
await SpecService.uploadNewSpec(specObject, fileName);
await SpecService.uploadNewSpec(
specObject,
fileName,
extension,
specFile.buffer.toString()
);
await ApiResponseHandler.success(res, null);
} catch (err) {
await ApiResponseHandler.error(res, err);
Expand All @@ -63,13 +79,35 @@ export const updateSpecHandler = async (req: Request, res: Response) => {
?.split(".json")[0]
?.split(".yaml")[0]
?.split(".yml")[0];
let extension = undefined;
if (specFile.mimetype === "application/json") {
extension = SpecExtension.JSON;
} else if (specFile.mimetype === "text/yaml") {
extension = SpecExtension.YAML;
} else {
throw new Error400BadRequest(
"Only .json, .yaml, and .yml format allowed."
);
}
if (!fileName) {
throw new Error400BadRequest("No filename provided.");
}
const openApiSpecRepository = AppDataSource.getRepository(OpenApiSpec);
const exisitingSpec = await openApiSpecRepository.findOneBy({
name: fileName,
});
if (!exisitingSpec) {
throw new Error400BadRequest("Spec file does not exist, cannot update.");
}
const specObject: JSONValue = yaml.load(
specFile.buffer.toString()
) as JSONValue;
await SpecService.updateSpec(specObject, fileName);
await SpecService.updateSpec(
specObject,
fileName,
extension,
specFile.buffer.toString()
);
await ApiResponseHandler.success(res, null);
} catch (err) {
await ApiResponseHandler.error(res, err);
Expand Down
5 changes: 5 additions & 0 deletions backend/src/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,8 @@ export enum RiskScore {
MEDIUM = "medium",
HIGH = "high",
}

export enum SpecExtension {
JSON = "json",
YAML = "yaml",
}
3 changes: 2 additions & 1 deletion backend/src/services/endpoints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IsNull, Raw } from "typeorm";
import { isSuspectedParamater } from "../../utils";
import { ApiEndpoint, ApiTrace, OpenApiSpec } from "../../../models";
import { AppDataSource } from "../../data-source";
import { RestMethod } from "../../enums";
import { RestMethod, SpecExtension } from "../../enums";
import { ScannerService } from "../scanner/scan";

interface GenerateEndpoint {
Expand Down Expand Up @@ -218,6 +218,7 @@ export class EndpointsService {
endpoint.openapiSpec = spec;
}
spec.spec = JSON.stringify(openApiSpec, null, 2);
spec.extension = SpecExtension.JSON;
await openApiSpecRepository.save(spec);
await apiEndpointRepository.save(endpoints);
});
Expand Down
21 changes: 16 additions & 5 deletions backend/src/services/spec/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { v4 as uuidv4 } from "uuid";
import { Not } from "typeorm";
import { RestMethod } from "../../enums";
import { RestMethod, SpecExtension } from "../../enums";
import {
ApiEndpoint,
ApiTrace,
Expand All @@ -20,9 +20,14 @@ export class SpecService {
return specList;
}

static async updateSpec(specObject: JSONValue, fileName: string) {
static async updateSpec(
specObject: JSONValue,
fileName: string,
extension: SpecExtension,
specString: string
) {
await this.deleteSpec(fileName);
await this.uploadNewSpec(specObject, fileName);
await this.uploadNewSpec(specObject, fileName, extension, specString);
}

static async deleteSpec(fileName: string) {
Expand All @@ -48,7 +53,12 @@ export class SpecService {
await openApiSpecRepository.remove(openApiSpec);
}

static async uploadNewSpec(specObject: JSONValue, fileName: string) {
static async uploadNewSpec(
specObject: JSONValue,
fileName: string,
extension: SpecExtension,
specString: string
) {
const servers: any[] = specObject["servers"];
const paths: JSONValue = specObject["paths"];

Expand All @@ -67,8 +77,9 @@ export class SpecService {
if (!existingSpec) {
existingSpec = new OpenApiSpec();
existingSpec.name = fileName;
existingSpec.extension = extension;
}
existingSpec.spec = JSON.stringify(specObject);
existingSpec.spec = specString;
const pathKeys = Object.keys(paths);
const endpoints: {
similarEndpoints: ApiEndpoint[];
Expand Down
5 changes: 5 additions & 0 deletions common/src/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,8 @@ export enum ConnectionType {
AWS = "AWS",
GCP = "GCP",
}

export enum SpecExtension {
JSON = "json",
YAML = "yaml",
}
3 changes: 2 additions & 1 deletion common/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AlertType, ConnectionType, RestMethod, RiskScore } from "./enums";
import { AlertType, ConnectionType, RestMethod, RiskScore, SpecExtension } from "./enums";

export interface Meta {
incoming: boolean;
Expand Down Expand Up @@ -127,6 +127,7 @@ export interface OpenApiSpec {
name: string;
spec: string;
isAutoGenerated: boolean;
extension: SpecExtension;
}

export interface Connection {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Endpoint/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const EndpointOverview: React.FC<EndpointOverviewProps> = React.memo(
overflowY={{ base: "unset", lg: "scroll" }}
h={{ base: "unset", lg: "full" }}
>
<Highlight {...defaultProps} theme={theme} code={openAPISpec} language="yaml">
<Highlight {...defaultProps} theme={theme} code={endpoint?.openapiSpec?.spec || "No spec."} language={endpoint?.openapiSpec?.extension || "yaml"}>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre
className={className}
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/pages/endpoint/[endpointUUID].tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import ErrorPage from "next/error";
import { SideNavLinkDestination } from "../../components/Sidebar/NavLinkUtils";
import { SidebarLayoutShell } from "../../components/SidebarLayoutShell";
import EndpointPage from "../../components/Endpoint";
Expand All @@ -11,16 +12,23 @@ const Endpoint = () => {
const { endpointUUID } = router.query;
const [fetching, setFetching] = useState<boolean>(true);
const [endpoint, setEndpoint] = useState<ApiEndpointDetailed>();
const [notFound, setNotFound] = useState<boolean>(false);
useEffect(() => {
const fetchEndpoint = async () => {
const res = await getEndpoint(endpointUUID?.toString());
if (!res) {
setNotFound(true);
}
setEndpoint(res);
setFetching(false);
}
if (endpointUUID) {
fetchEndpoint();
}
}, [endpointUUID])
if (notFound) {
return <ErrorPage statusCode={404} />
}
return (
<SidebarLayoutShell currentTab={SideNavLinkDestination.Endpoints}>
<EndpointPage endpoint={endpoint} fetching={fetching} />
Expand Down

0 comments on commit 6c4d333

Please sign in to comment.