Skip to content

Commit

Permalink
fix: Disable schema validation by default (#278)
Browse files Browse the repository at this point in the history
* add `schemaValidation` flag to `IAgentOptions` to enable validation of inputs and outputs.
* update config templates to set `schemaValidation` flag to false
* update integration tests to consider validation

Closes #255
Closes #275
  • Loading branch information
mirceanis committed Nov 23, 2020
1 parent b97ff3b commit 7bb77cd
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 38 deletions.
4 changes: 3 additions & 1 deletion __tests__/localAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
IKeyManager,
IDataStore,
IMessageHandler,
IAgentOptions,
} from '../packages/daf-core/src'
import { MessageHandler } from '../packages/daf-message-handler/src'
import { KeyManager } from '../packages/daf-key-manager/src'
Expand Down Expand Up @@ -61,7 +62,7 @@ let agent: TAgent<
>
let dbConnection: Promise<Connection>

const setup = async (): Promise<boolean> => {
const setup = async (options?: IAgentOptions): Promise<boolean> => {
dbConnection = createConnection({
type: 'sqlite',
database: databaseFile,
Expand All @@ -81,6 +82,7 @@ const setup = async (): Promise<boolean> => {
ICredentialIssuer &
ISelectiveDisclosure
>({
...options,
context: {
// authenticatedDid: 'did:example:3456'
},
Expand Down
46 changes: 25 additions & 21 deletions __tests__/restAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
IKeyManager,
IDataStore,
IMessageHandler,
IAgentOptions,
} from '../packages/daf-core/src'
import { MessageHandler } from '../packages/daf-message-handler/src'
import { KeyManager } from '../packages/daf-key-manager/src'
Expand Down Expand Up @@ -59,27 +60,29 @@ let dbConnection: Promise<Connection>
let serverAgent: IAgent
let restServer: Server

const getAgent = () => createAgent<
IIdentityManager &
IKeyManager &
IDataStore &
IDataStoreORM &
IResolver &
IMessageHandler &
IDIDComm &
ICredentialIssuer &
ISelectiveDisclosure
>({
plugins: [
new AgentRestClient({
url: 'http://localhost:' + port + basePath,
enabledMethods: Object.keys(serverAgent.getSchema().components.methods),
schema: serverAgent.getSchema()
}),
],
})
const getAgent = (options?: IAgentOptions) =>
createAgent<
IIdentityManager &
IKeyManager &
IDataStore &
IDataStoreORM &
IResolver &
IMessageHandler &
IDIDComm &
ICredentialIssuer &
ISelectiveDisclosure
>({
...options,
plugins: [
new AgentRestClient({
url: 'http://localhost:' + port + basePath,
enabledMethods: Object.keys(serverAgent.getSchema().components.methods),
schema: serverAgent.getSchema(),
}),
],
})

const setup = async (): Promise<boolean> => {
const setup = async (options?: IAgentOptions): Promise<boolean> => {
dbConnection = createConnection({
type: 'sqlite',
database: databaseFile,
Expand All @@ -89,6 +92,7 @@ const setup = async (): Promise<boolean> => {
})

serverAgent = new Agent({
...options,
plugins: [
new KeyManager({
store: new KeyStore(dbConnection, new SecretBox(secretKey)),
Expand Down Expand Up @@ -139,7 +143,7 @@ const setup = async (): Promise<boolean> => {
const agentRouter = AgentRouter({
getAgentForRequest: async (req) => serverAgent,
exposedMethods: serverAgent.availableMethods(),
basePath
basePath,
})

return new Promise((resolve) => {
Expand Down
6 changes: 3 additions & 3 deletions __tests__/shared/keyManager.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { TAgent, IIdentityManager, IKeyManager } from '../../packages/daf-core/src'
import { TAgent, IIdentityManager, IKeyManager, IAgentOptions } from '../../packages/daf-core/src'

type ConfiguredAgent = TAgent<IIdentityManager & IKeyManager>

export default (testContext: {
getAgent: () => ConfiguredAgent
setup: () => Promise<boolean>
setup: (options?: IAgentOptions) => Promise<boolean>
tearDown: () => Promise<boolean>
}) => {
describe('key manager', () => {
Expand Down Expand Up @@ -64,7 +64,7 @@ export default (testContext: {
//@ts-ignore
type: 'foobar',
}),
).rejects.toThrow('No enum match for: foobar')
).rejects.toThrow('Key type not supported: foobar')
})

it('should create key with meta data', async () => {
Expand Down
33 changes: 27 additions & 6 deletions __tests__/shared/resolveDid.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { TAgent, IResolver, ValidationError } from '../../packages/daf-core/src'
import { TAgent, IResolver, ValidationError, IAgentOptions } from '../../packages/daf-core/src'

type ConfiguredAgent = TAgent<IResolver>

export default (testContext: {
getAgent: () => ConfiguredAgent
setup: () => Promise<boolean>
getAgent: (options?: IAgentOptions) => ConfiguredAgent
setup: (options?: IAgentOptions) => Promise<boolean>
tearDown: () => Promise<boolean>
}) => {
describe('resolving didUrl', () => {
Expand All @@ -24,17 +24,38 @@ export default (testContext: {
})

it('should throw an error for unsupported did methods', async () => {
await expect(agent.resolveDid({ didUrl: 'did:foo:bar' })).rejects.toThrow("Unsupported DID method: 'foo'")
await expect(agent.resolveDid({ didUrl: 'did:foo:bar' })).rejects.toThrow(
"Unsupported DID method: 'foo'",
)
})

it('should throw error when resolving garbage', async () => {
//@ts-ignore
await expect(agent.resolveDid()).rejects.toHaveProperty('name', 'Error')
//@ts-ignore
await expect(agent.resolveDid({})).rejects.toHaveProperty('name', 'Error')
//@ts-ignore
await expect(agent.resolveDid({ didUrl: 1 })).rejects.toThrow()
})
})

describe('resolving didUrl with validation', () => {
let agent: ConfiguredAgent

beforeAll(async () => {
await testContext.setup({ schemaValidation: true })
agent = testContext.getAgent({ schemaValidation: true })
return true
})
afterAll(testContext.tearDown)

it('should throw validation error', async () => {
//@ts-ignore
await expect(agent.resolveDid()).rejects.toHaveProperty('name', 'ValidationError')
//@ts-ignore
await expect(agent.resolveDid({})).rejects.toHaveProperty('name', 'ValidationError')
//@ts-ignore
await expect(agent.resolveDid({didUrl: 1})).rejects.toHaveProperty('name', 'ValidationError')

await expect(agent.resolveDid({ didUrl: 1 })).rejects.toHaveProperty('name', 'ValidationError')
})
})
}
1 change: 1 addition & 0 deletions docs/api/daf-core.iagentoptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ export interface IAgentOptions
| [context](./daf-core.iagentoptions.context.md) | Record&lt;string, any&gt; | The context object that will be available to the plugin methods |
| [overrides](./daf-core.iagentoptions.overrides.md) | [IPluginMethodMap](./daf-core.ipluginmethodmap.md) | The map of plugin methods. Can be used to override methods provided by plugins, or to add additional methods without writing a plugin |
| [plugins](./daf-core.iagentoptions.plugins.md) | [IAgentPlugin](./daf-core.iagentplugin.md)<!-- -->\[\] | The array of agent plugins |
| [schemaValidation](./daf-core.iagentoptions.schemavalidation.md) | boolean | Flag that enables schema validation for plugin methods. false |

15 changes: 15 additions & 0 deletions docs/api/daf-core.iagentoptions.schemavalidation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [daf-core](./daf-core.md) &gt; [IAgentOptions](./daf-core.iagentoptions.md) &gt; [schemaValidation](./daf-core.iagentoptions.schemavalidation.md)

## IAgentOptions.schemaValidation property

Flag that enables schema validation for plugin methods.

false

<b>Signature:</b>

```typescript
schemaValidation?: boolean;
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"docs:reference": "api-documenter markdown -i ./temp -o ./docs/api",
"docs:clean-temp": "rm -rf ./temp",
"test": "jest --config=jest.json --maxWorkers=2",
"test:watch": "jest --config=jest.json --watch --verbose",
"test:watch": "jest --config=jest.json --watch --verbose --coverage=false",
"daf": "./packages/daf-cli/bin/daf.js",
"prettier": "prettier --write '{packages,__tests__, !build}/**/*.ts'",
"prettier:examples": "prettier --write __tests__/shared/documentationExamples.ts",
Expand Down
3 changes: 2 additions & 1 deletion packages/daf-cli/default/client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ server:
agent:
$require: daf-core#Agent
$args:
- plugins:
- schemaValidation: false
plugins:
- $require: daf-rest#AgentRestClient
$args:
- url: http://localhost:3332
Expand Down
3 changes: 2 additions & 1 deletion packages/daf-cli/default/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ messageHandler:
agent:
$require: daf-core#Agent
$args:
- plugins:
- schemaValidation: true
plugins:
- $require: daf-key-manager#KeyManager
$args:
- store:
Expand Down
25 changes: 25 additions & 0 deletions packages/daf-core/api/daf-core.api.json
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,31 @@
"startIndex": 1,
"endIndex": 3
}
},
{
"kind": "PropertySignature",
"canonicalReference": "daf-core!IAgentOptions#schemaValidation:member",
"docComment": "/**\n * Flag that enables schema validation for plugin methods.\n *\n * @default false\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "schemaValidation?: "
},
{
"kind": "Content",
"text": "boolean"
},
{
"kind": "Content",
"text": ";"
}
],
"releaseTag": "Public",
"name": "schemaValidation",
"propertyTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
}
}
],
"extendsTokenRanges": []
Expand Down
1 change: 1 addition & 0 deletions packages/daf-core/api/daf-core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface IAgentOptions {
context?: Record<string, any>
overrides?: IPluginMethodMap
plugins?: IAgentPlugin[]
schemaValidation?: boolean
}

// @public
Expand Down
3 changes: 1 addition & 2 deletions packages/daf-core/src/__tests__/agent.subscriber.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,13 @@ describe('daf-core agent', () => {
const errorHandler: IEventListener = {
eventTypes: ['error'],
onEvent: async () => {
console.log('throwing error in error handler')
throw new Error('barError')
},
}
const agent = new Agent({
plugins: [plugin, errorHandler],
})

await expect(agent.emit('foo', {})).rejects.toThrowError('ErrorEventHandlerError')
await expect(agent.emit('foo', {})).rejects.toThrow('ErrorEventHandlerError')
})
})
14 changes: 12 additions & 2 deletions packages/daf-core/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ export interface IAgentOptions {
* ```
*/
context?: Record<string, any>

/**
* Flag that enables schema validation for plugin methods.
*
* @default false
*/
schemaValidation?: boolean
}

/**
Expand All @@ -85,6 +92,7 @@ export class Agent implements IAgent {
readonly methods: IPluginMethodMap = {}

private schema: IAgentPluginSchema
private schemaValidation: boolean
private context?: Record<string, any>
private protectedMethods = ['execute', 'availableMethods', 'emit']

Expand Down Expand Up @@ -167,6 +175,8 @@ export class Agent implements IAgent {
this[method] = async (args: any) => this.execute(method, args)
}
}

this.schemaValidation = options?.schemaValidation || false
}

/**
Expand Down Expand Up @@ -215,11 +225,11 @@ export class Agent implements IAgent {
Debug('daf:agent:' + method)('%o', args)
if (!this.methods[method]) throw Error('Method not available: ' + method)
const _args = args || {}
if (this.schema.components.methods[method]) {
if (this.schemaValidation && this.schema.components.methods[method]) {
validateArguments(method, _args, this.schema)
}
const result = await this.methods[method](_args, { ...this.context, agent: this })
if (this.schema.components.methods[method]) {
if (this.schemaValidation && this.schema.components.methods[method]) {
validateReturnType(method, result, this.schema)
}
Debug('daf:agent:' + method + ':result')('%o', result)
Expand Down

0 comments on commit 7bb77cd

Please sign in to comment.