-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(plugins): add JSON validation schema plugin (#62)
* chore: add root node_modules to gitignore * feat: setup json folder * feat(json): add ajv * feat(json): fixed plugin and tests * chore: package rename * Revert "chore: package rename" This reverts commit efe1965. * chore: rename module * fix: removed commands --------- Co-authored-by: Puria Nafisi Azizi <[email protected]>
- Loading branch information
Showing
9 changed files
with
264 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,3 +46,4 @@ | |
!/docs/*.mjs | ||
!/docs/*.json | ||
|
||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../.npmignore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"name": "@slangroom/json-schema", | ||
"version": "1.9.6", | ||
"dependencies": { | ||
"@slangroom/core": "workspace:*", | ||
"@slangroom/shared": "workspace:*", | ||
"ajv": "^8.12.0" | ||
}, | ||
"repository": "https://github.com/dyne/slangroom", | ||
"license": "AGPL-3.0-only", | ||
"type": "module", | ||
"main": "./build/esm/src/index.js", | ||
"types": "./build/esm/src/index.d.ts", | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./build/esm/src/index.d.ts", | ||
"default": "./build/esm/src/index.js" | ||
} | ||
}, | ||
"./*": { | ||
"import": { | ||
"types": "./build/esm/src/*.d.ts", | ||
"default": "./build/esm/src/*.js" | ||
} | ||
} | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from '@slangroom/json-schema/plugin'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { Plugin } from '@slangroom/core'; | ||
import Ajv, { type ValidationError } from 'ajv'; | ||
|
||
export { ValidationError }; | ||
|
||
// | ||
|
||
const p = new Plugin(); | ||
|
||
export const ARG_JSON_DATA = 'json_data'; | ||
export const ARG_JSON_SCHEMA = 'json_schema'; | ||
export const PHRASE_VALIDATE_JSON = 'validate json'; | ||
|
||
export const SENTENCE_VALIDATE_JSON = (dataKey: string, schemaKey: string, outputKey: string) => | ||
`Given I send ${ARG_JSON_DATA} '${dataKey}' and send ${ARG_JSON_SCHEMA} '${schemaKey}' and ${PHRASE_VALIDATE_JSON} and output into '${outputKey}' | ||
Given I have a 'string dictionary' named '${outputKey}'`; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export const validateJSON = p.new( | ||
[ARG_JSON_DATA, ARG_JSON_SCHEMA], | ||
PHRASE_VALIDATE_JSON, | ||
async (ctx) => { | ||
const data = ctx.fetch(ARG_JSON_DATA); | ||
const schema = ctx.fetch(ARG_JSON_SCHEMA); | ||
|
||
try { | ||
const ajv = new Ajv.default({ allErrors: true }); | ||
|
||
// @ts-ignore | ||
const validate = ajv.compile(schema); | ||
validate(data); | ||
|
||
// @ts-ignore | ||
return ctx.pass({ | ||
errors: validate.errors ?? [], | ||
}); | ||
} catch (e) { | ||
console.log(e.message); | ||
return ctx.fail('JSON Schema not valid' + e); | ||
} | ||
}, | ||
); | ||
|
||
export const JSONSchema = p; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import test from 'ava'; | ||
import { Slangroom } from '@slangroom/core'; | ||
import { JSONSchema, SENTENCE_VALIDATE_JSON, ValidationError } from '@slangroom/json-schema'; | ||
|
||
const KEY_DATA = 'data'; | ||
const KEY_SCHEMA = 'schema'; | ||
const KEY_OUTPUT = 'out'; | ||
const SENTENCE = SENTENCE_VALIDATE_JSON(KEY_DATA, KEY_SCHEMA, KEY_OUTPUT); | ||
|
||
test('validate valid data with valid schema', async (t) => { | ||
const script = ` | ||
Rule unknown ignore | ||
${SENTENCE} | ||
Then print data | ||
`; | ||
|
||
const slangroom = new Slangroom(JSONSchema); | ||
|
||
const res = await slangroom.execute(script, { | ||
data: { | ||
[KEY_DATA]: 'nice', | ||
[KEY_SCHEMA]: { | ||
type: 'string', | ||
}, | ||
}, | ||
}); | ||
|
||
const output = res.result[KEY_OUTPUT] as unknown as { errors: ValidationError[] }; | ||
t.deepEqual(output.errors, []); | ||
}); | ||
|
||
test('validate invalid data with valid schema', async (t) => { | ||
const script = ` | ||
Rule unknown ignore | ||
${SENTENCE} | ||
Then print data | ||
`; | ||
|
||
const slangroom = new Slangroom(JSONSchema); | ||
|
||
const res = await slangroom.execute(script, { | ||
data: { | ||
[KEY_DATA]: 12, | ||
[KEY_SCHEMA]: { | ||
type: 'string', | ||
}, | ||
}, | ||
}); | ||
|
||
const output = res.result[KEY_OUTPUT] as unknown as { errors: ValidationError[] }; | ||
t.true(Array.isArray(output.errors) && output.errors.length > 0); | ||
}); | ||
|
||
test('load invalid schema', async (t) => { | ||
const script = ` | ||
Rule unknown ignore | ||
${SENTENCE} | ||
Then print data | ||
`; | ||
|
||
const slangroom = new Slangroom(JSONSchema); | ||
|
||
let error; | ||
try { | ||
await slangroom.execute(script, { | ||
data: { | ||
[KEY_DATA]: 12, | ||
[KEY_SCHEMA]: { | ||
invalid_key: 'string', | ||
}, | ||
}, | ||
}); | ||
} catch (e) { | ||
error = 'Invalid JSON schema'; | ||
} | ||
|
||
t.assert(error); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../tsconfig.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import test from 'ava'; | ||
import { Slangroom } from '@slangroom/core'; | ||
import { wallet } from '@slangroom/wallet'; | ||
import { JsonableArray } from '@slangroom/shared'; | ||
|
||
test('Create VC SD JWT', async (t) => { | ||
const scriptCreate = ` | ||
Rule unknown ignore | ||
Given I create p-256 key and output into 'issuer_jwk' | ||
Given I create p-256 key and output into 'holder_jwk' | ||
Given I send sk 'holder_jwk' and create p-256 public key and output into 'holder_public_jwk' | ||
Given I send sk 'issuer_jwk' and create p-256 public key and output into 'issuer_public_jwk' | ||
Given I send jwk 'issuer_jwk' and send holder 'holder_public_jwk' and send object 'object' and send fields 'fields' and create vc sd jwt and output into 'vcsdjwt' | ||
Given I send token 'vcsdjwt' and pretty print sd jwt and output into 'pretty_jwt' | ||
Given I have a 'string dictionary' named 'issuer_jwk' | ||
Given I have a 'string dictionary' named 'holder_jwk' | ||
Given I have a 'string dictionary' named 'holder_public_jwk' | ||
Given I have a 'string dictionary' named 'issuer_public_jwk' | ||
Given I have a 'string' named 'vcsdjwt' | ||
Given I have a 'string dictionary' named 'pretty_jwt' | ||
Then print data | ||
`; | ||
const nonce = 'nIdBbNgRqCXBl8YOkfVdg=='; | ||
const slangroom = new Slangroom(wallet); | ||
const res = await slangroom.execute(scriptCreate, { | ||
keys: { | ||
object: { | ||
name: 'test person', | ||
age: 25, | ||
}, | ||
fields: ['name', 'age'], | ||
}, | ||
}); | ||
t.truthy(res.result['vcsdjwt']); | ||
t.is((res.result['pretty_jwt'] as JsonableArray).length, 3); | ||
|
||
const scriptPrepare = ` | ||
Rule unknown ignore | ||
Given I send verifier_url 'verifier_url' and send issued_vc 'issued_vc' and send disclosed 'disclosed' and send nonce 'nonce' and send holder 'holder_jwk' and present vc sd jwt and output into 'presentation' | ||
Given I have a 'string' named 'presentation' | ||
Then print data | ||
`; | ||
const res2 = await slangroom.execute(scriptPrepare, { | ||
keys: { | ||
disclosed: ['name'], | ||
nonce, | ||
verifier_url: 'https://valid.verifier.url', | ||
holder_jwk: res.result['holder_jwk'] || {}, | ||
issued_vc: res.result['vcsdjwt'] || '', | ||
}, | ||
}); | ||
t.truthy(res2.result['presentation']); | ||
|
||
const scriptVerify = ` | ||
Rule unknown ignore | ||
Given I send verifier_url 'verifier_url' and send issued_vc 'presentation' and send nonce 'nonce' and send issuer 'issuer_jwk' and verify vc sd jwt and output into 'verification' | ||
Given I have a 'string dictionary' named 'verification' | ||
Then print data | ||
`; | ||
const res3 = await slangroom.execute(scriptVerify, { | ||
keys: { | ||
nonce, | ||
verifier_url: 'https://valid.verifier.url', | ||
issuer_jwk: res.result['issuer_public_jwk'] || {}, | ||
presentation: res2.result['presentation'] || '', | ||
}, | ||
}); | ||
t.truthy(res3.result['verification']); | ||
}); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.