Skip to content

Commit 134b64b

Browse files
Harshdev098petermetz
authored andcommitted
fix: Fixed deployContract to throw error if get additional property
Fix: #3507 - Fixed the deployContract to throw error if get any additional property - Used ajv and to validate the requests - Used json-schema-ref-parser to handle the nullable property in the openAPI as ajv was throwing errors becuase it require a type keyword when using nullable, while openapi.json uses nullable in contexts. So preferred to go with ref-parser instead of updating the openAPI Signed-off-by: Harshdev098 <[email protected]>
1 parent 9de3e4c commit 134b64b

File tree

4 files changed

+87
-7
lines changed

4 files changed

+87
-7
lines changed

packages/cactus-plugin-ledger-connector-ethereum/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,13 @@
6565
"webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js"
6666
},
6767
"dependencies": {
68+
"@apidevtools/json-schema-ref-parser": "12.0.1",
6869
"@ethereumjs/common": "4.0.0",
6970
"@ethereumjs/tx": "5.0.0",
7071
"@hyperledger/cactus-common": "2.1.0",
7172
"@hyperledger/cactus-core": "2.1.0",
7273
"@hyperledger/cactus-core-api": "2.1.0",
74+
"ajv": "8.17.1",
7375
"axios": "1.8.4",
7476
"ethers": "6.8.1",
7577
"express": "5.1.0",

packages/cactus-plugin-ledger-connector-ethereum/src/main/typescript/web-services/deploy-contract-v1-endpoint.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { Express, Request, Response } from "express";
2+
import { Ajv } from "ajv";
3+
import RefParser from "@apidevtools/json-schema-ref-parser";
24

35
import {
46
IWebServiceEndpoint,
@@ -22,6 +24,53 @@ import OAS from "../../json/openapi.json";
2224
import { ERR_INVALID_RESPONSE } from "web3";
2325
import { isWeb3Error } from "../public-api";
2426

27+
async function preprocessSchema() {
28+
const resolvedSchema = await RefParser.dereference(OAS);
29+
function adjustNullable(obj: Record<string, unknown>) {
30+
if (typeof obj !== "object" || obj === null) return;
31+
if ("nullable" in obj && !("type" in obj)) {
32+
delete obj.nullable;
33+
}
34+
if (obj.nullable === true && obj.type && typeof obj.type === "string") {
35+
obj.type = [obj.type, "null"];
36+
delete obj.nullable;
37+
}
38+
if (obj.nullable === false) {
39+
delete obj.nullable;
40+
}
41+
for (const key in obj) {
42+
if (typeof obj[key] === "object" && obj[key] !== null) {
43+
adjustNullable(obj[key] as Record<string, unknown>);
44+
}
45+
}
46+
}
47+
48+
adjustNullable(resolvedSchema as Record<string, unknown>);
49+
return resolvedSchema;
50+
}
51+
52+
let validateDeployContract: ReturnType<Ajv["compile"]> | undefined;
53+
async function getValidateDeployContract(): Promise<
54+
ReturnType<Ajv["compile"]>
55+
> {
56+
if (validateDeployContract) {
57+
return validateDeployContract;
58+
}
59+
60+
const ajv = new Ajv({
61+
allErrors: true,
62+
strict: false,
63+
allowMatchingProperties: true,
64+
});
65+
const processedSchema = await preprocessSchema();
66+
ajv.addSchema(processedSchema, "openapi.json");
67+
68+
validateDeployContract = ajv.compile({
69+
$ref: "openapi.json#/components/schemas/DeployContractV1Request",
70+
});
71+
return validateDeployContract;
72+
}
73+
2574
export interface IDeployContractSolidityBytecodeOptions {
2675
logLevel?: LogLevelDesc;
2776
connector: PluginLedgerConnectorEthereum;
@@ -88,6 +137,18 @@ export class DeployContractEndpoint implements IWebServiceEndpoint {
88137
public async handleRequest(req: Request, res: Response): Promise<void> {
89138
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
90139
this.log.debug(reqTag);
140+
141+
const validate = await getValidateDeployContract();
142+
const isValid = validate(req.body);
143+
if (!isValid) {
144+
const errorDetails = JSON.stringify(validate.errors);
145+
this.log.debug(`Validation failed for ${reqTag}: ${errorDetails}`);
146+
res.status(400).json({
147+
message: "Invalid request body",
148+
errors: validate.errors,
149+
});
150+
return;
151+
}
91152
try {
92153
res
93154
.status(200)

packages/cactus-plugin-ledger-connector-ethereum/src/test/typescript/integration/geth-contract-deploy-and-invoke-using-json-object-v1.test.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,8 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
243243
});
244244

245245
test("deployContract with additional parameters should fail", async () => {
246-
try {
247-
await apiClient.deployContract({
246+
await expect(
247+
apiClient.deployContract({
248248
contract: {
249249
contractJSON: HelloWorldContractJson,
250250
},
@@ -255,11 +255,15 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
255255
},
256256
gas: 1000000,
257257
fake: 4,
258-
} as DeployContractV1Request);
259-
fail("Expected deployContract call to fail but it succeeded.");
260-
} catch (error) {
261-
console.log("deployContract failed as expected");
262-
}
258+
} as DeployContractV1Request),
259+
).rejects.toMatchObject({
260+
response: {
261+
status: 400,
262+
data: {
263+
message: expect.stringContaining("Invalid request body"),
264+
},
265+
},
266+
});
263267
});
264268

265269
//////////////////////////////////

yarn.lock

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,17 @@ __metadata:
805805
languageName: node
806806
linkType: hard
807807

808+
"@apidevtools/json-schema-ref-parser@npm:12.0.1":
809+
version: 12.0.1
810+
resolution: "@apidevtools/json-schema-ref-parser@npm:12.0.1"
811+
dependencies:
812+
"@jsdevtools/ono": "npm:^7.1.3"
813+
"@types/json-schema": "npm:^7.0.15"
814+
js-yaml: "npm:^4.1.0"
815+
checksum: 10/1ebe4b623dc841ac7137abb68e573a91350fcca38185379da52e1ab888fcb4cf706026bc41436dbb61a82ca830c8221e04b8432252bbb34815cfee5f290d0a22
816+
languageName: node
817+
linkType: hard
818+
808819
"@apidevtools/json-schema-ref-parser@npm:^11.6.2":
809820
version: 11.6.4
810821
resolution: "@apidevtools/json-schema-ref-parser@npm:11.6.4"
@@ -10616,6 +10627,7 @@ __metadata:
1061610627
version: 0.0.0-use.local
1061710628
resolution: "@hyperledger/cactus-plugin-ledger-connector-ethereum@workspace:packages/cactus-plugin-ledger-connector-ethereum"
1061810629
dependencies:
10630+
"@apidevtools/json-schema-ref-parser": "npm:12.0.1"
1061910631
"@ethereumjs/common": "npm:4.0.0"
1062010632
"@ethereumjs/tx": "npm:5.0.0"
1062110633
"@hyperledger/cactus-common": "npm:2.1.0"
@@ -10630,6 +10642,7 @@ __metadata:
1063010642
"@types/minimist": "npm:1.2.2"
1063110643
"@types/sanitize-html": "npm:2.9.5"
1063210644
"@types/uuid": "npm:10.0.0"
10645+
ajv: "npm:8.17.1"
1063310646
axios: "npm:1.8.4"
1063410647
body-parser: "npm:1.20.3"
1063510648
chalk: "npm:4.1.2"

0 commit comments

Comments
 (0)