mirror of
https://github.com/lowdefy/lowdefy.git
synced 2025-02-11 14:20:07 +08:00
fix: Refactored connection-redis plugin to have non restrictive schemas.
This commit is contained in:
parent
ee2315d69c
commit
f8d9f8e149
@ -23,47 +23,33 @@ test('All requests are present', () => {
|
|||||||
expect(Redis.requests.Redis).toBeDefined();
|
expect(Redis.requests.Redis).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('valid connection schema, with url', () => {
|
test('valid connection schema, with string', () => {
|
||||||
const connection = {
|
const connection = {
|
||||||
url: '/path',
|
connection: '/path',
|
||||||
};
|
};
|
||||||
expect(validate({ schema, data: connection })).toEqual({ valid: true });
|
expect(validate({ schema, data: connection })).toEqual({ valid: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
test('valid connection schema, with socket', () => {
|
test('valid connection schema, with object', () => {
|
||||||
const connection = {
|
const connection = {
|
||||||
socket: {
|
connection: {
|
||||||
host: 'https://example.com/redis',
|
socket: {
|
||||||
port: 6379,
|
host: 'https://example.com/redis',
|
||||||
|
port: 6379,
|
||||||
|
},
|
||||||
|
username: 'username',
|
||||||
|
password: 'password',
|
||||||
|
database: 5,
|
||||||
},
|
},
|
||||||
username: 'username',
|
|
||||||
password: 'password',
|
|
||||||
database: 5,
|
|
||||||
};
|
};
|
||||||
expect(validate({ schema, data: connection })).toEqual({ valid: true });
|
expect(validate({ schema, data: connection })).toEqual({ valid: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
test('invalid connection schema, with all properties', () => {
|
test('invalid connection schema', () => {
|
||||||
const connection = {
|
const connection = {
|
||||||
url: '/path',
|
connection: null,
|
||||||
socket: {
|
|
||||||
host: 'https://example.com/redis',
|
|
||||||
port: 6379,
|
|
||||||
},
|
|
||||||
username: 'username',
|
|
||||||
password: 'password',
|
|
||||||
database: 0,
|
|
||||||
};
|
};
|
||||||
expect(() => validate({ schema, data: connection })).toThrow(
|
expect(() => validate({ schema, data: connection })).toThrow(
|
||||||
'Redis connection should have required property "url" or "socket.host" and "socket.port".'
|
'Redis connection property "connection" should be a string or object.'
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('url is not a string', () => {
|
|
||||||
const connection = {
|
|
||||||
url: true,
|
|
||||||
};
|
|
||||||
expect(() => validate({ schema, data: connection })).toThrow(
|
|
||||||
'Redis property "url" should be a string.'
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -19,23 +19,49 @@ import { createClient } from 'redis';
|
|||||||
import schema from './schema.js';
|
import schema from './schema.js';
|
||||||
|
|
||||||
async function Redis({ request, connection }) {
|
async function Redis({ request, connection }) {
|
||||||
const client = new createClient(connection);
|
const connectionObject = type.isString(connection.connection)
|
||||||
|
? { url: connection.connection }
|
||||||
|
: connection.connection;
|
||||||
|
|
||||||
|
const client = new createClient(connectionObject);
|
||||||
client.on('error', (error) => {
|
client.on('error', (error) => {
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { command, parameters, modifiers } = request;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { command, params, modifiers } = request;
|
|
||||||
await client.connect();
|
await client.connect();
|
||||||
const commandParams = type.isArray(params) ? params : [params];
|
} catch (error) {
|
||||||
const commandReturn = await client[command.toUpperCase()](...commandParams, modifiers);
|
throw new Error(`Connection refused.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type.isFunction(client[command.toUpperCase()])) {
|
||||||
|
throw new Error(`Invalid redis command "${command}".`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type.isArray(parameters)) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid command, command "${command}" parameters should be an array, received ${JSON.stringify(
|
||||||
|
parameters
|
||||||
|
)}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const upperCaseModifiers = Object.entries(modifiers).reduce((acc, [key, value]) => {
|
||||||
|
acc[key.toUpperCase()] = value;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const commandReturn = await client[command.toUpperCase()](...parameters, upperCaseModifiers);
|
||||||
await client.quit();
|
await client.quit();
|
||||||
return commandReturn;
|
return commandReturn;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code !== 'ECONNREFUSED') {
|
client.quit();
|
||||||
await client.quit();
|
throw new Error(
|
||||||
}
|
`Invalid command "${command}" parameters, received ${JSON.stringify(parameters)}.`
|
||||||
throw error;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,59 +21,30 @@ const { checkRead, checkWrite } = Redis.meta;
|
|||||||
const schema = Redis.schema;
|
const schema = Redis.schema;
|
||||||
|
|
||||||
test('valid request schema, with url', () => {
|
test('valid request schema, with url', () => {
|
||||||
const connection = {
|
const request = {
|
||||||
command: 'set',
|
command: 'set',
|
||||||
params: ['key', 10],
|
parameters: ['key', 10],
|
||||||
};
|
};
|
||||||
expect(validate({ schema, data: connection })).toEqual({ valid: true });
|
expect(validate({ schema, data: request })).toEqual({ valid: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
test('command is not a string', () => {
|
test('command is not a string', () => {
|
||||||
const connection = {
|
const request = {
|
||||||
command: true,
|
command: true,
|
||||||
params: ['key', 'value'],
|
parameters: ['key', 'value'],
|
||||||
};
|
};
|
||||||
expect(() => validate({ schema, data: connection })).toThrow(
|
expect(() => validate({ schema, data: request })).toThrow(
|
||||||
'Redis request property "command" should be a string.'
|
'Redis request property "command" should be a string.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('command is not valid', () => {
|
test('parameters is not an array', () => {
|
||||||
const connection = {
|
const request = {
|
||||||
command: 'notValidCommand',
|
|
||||||
params: ['key', 'value'],
|
|
||||||
};
|
|
||||||
expect(() => validate({ schema, data: connection })).toThrow(
|
|
||||||
'Redis request property "command" is not a valid value.'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('params are not valid for command', () => {
|
|
||||||
const connection = {
|
|
||||||
command: 'get',
|
|
||||||
params: ['key', 'value'],
|
|
||||||
};
|
|
||||||
expect(() => validate({ schema, data: connection })).toThrow(
|
|
||||||
'Redis request property "params" should be a string.'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('params are not valid for command', () => {
|
|
||||||
const connection = {
|
|
||||||
command: 'set',
|
command: 'set',
|
||||||
params: 'key',
|
parameters: 'string',
|
||||||
};
|
};
|
||||||
expect(() => validate({ schema, data: connection })).toThrow(
|
expect(() => validate({ schema, data: request })).toThrow(
|
||||||
'Redis request property "params" should be an array.'
|
'Redis request property "parameters" should be an array.'
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('params are not present', () => {
|
|
||||||
const connection = {
|
|
||||||
command: 'set',
|
|
||||||
};
|
|
||||||
expect(() => validate({ schema, data: connection })).toThrow(
|
|
||||||
'Redis request property "params" should be present.'
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -21,11 +21,16 @@ export default {
|
|||||||
properties: {
|
properties: {
|
||||||
command: {
|
command: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
enum: ['get', 'set', 'hget', 'hset'],
|
|
||||||
description: 'Redis command to execute.',
|
description: 'Redis command to execute.',
|
||||||
errorMessage: {
|
errorMessage: {
|
||||||
type: 'Redis request property "command" should be a string.',
|
type: 'Redis request property "command" should be a string.',
|
||||||
enum: 'Redis request property "command" is not a valid value.',
|
},
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
type: 'array',
|
||||||
|
description: 'The parameters to use with the command.',
|
||||||
|
errorMessage: {
|
||||||
|
type: 'Redis request property "parameters" should be an array.',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
modifiers: {
|
modifiers: {
|
||||||
@ -38,37 +43,6 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ['command'],
|
required: ['command'],
|
||||||
if: {
|
|
||||||
properties: { command: { enum: ['get'] } },
|
|
||||||
},
|
|
||||||
then: {
|
|
||||||
properties: {
|
|
||||||
params: {
|
|
||||||
type: 'string',
|
|
||||||
errorMessage: {
|
|
||||||
type: 'Redis request property "params" should be a string.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
required: ['params'],
|
|
||||||
errorMessage: {
|
|
||||||
required: 'Redis request property "params" should be present.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
else: {
|
|
||||||
properties: {
|
|
||||||
params: {
|
|
||||||
type: 'array',
|
|
||||||
errorMessage: {
|
|
||||||
type: 'Redis request property "params" should be an array.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
required: ['params'],
|
|
||||||
errorMessage: {
|
|
||||||
required: 'Redis request property "params" should be present.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
errorMessage: {
|
errorMessage: {
|
||||||
type: 'Redis request properties should be an object.',
|
type: 'Redis request properties should be an object.',
|
||||||
},
|
},
|
||||||
|
@ -19,74 +19,16 @@ export default {
|
|||||||
title: 'Lowdefy Connection Schema - Redis',
|
title: 'Lowdefy Connection Schema - Redis',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
url: {
|
connection: {
|
||||||
type: 'string',
|
type: ['string', 'object'],
|
||||||
description:
|
description: 'Connection object or string to pass to the redis client.',
|
||||||
'The redis server url to connect to (redis[s]://[[username][:password]@][host][:port][/db-number])',
|
|
||||||
errorMessage: {
|
errorMessage: {
|
||||||
type: 'Redis property "url" should be a string.',
|
type: 'Redis connection property "connection" should be a string or object.',
|
||||||
},
|
|
||||||
},
|
|
||||||
socket: {
|
|
||||||
type: 'object',
|
|
||||||
description: 'Object defining socket connection properties.',
|
|
||||||
properties: {
|
|
||||||
host: {
|
|
||||||
type: 'string',
|
|
||||||
description: 'Hostname to connect to',
|
|
||||||
default: 'localhost',
|
|
||||||
errorMessage: {
|
|
||||||
type: 'Redis property "socket.host" should be a string.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
port: {
|
|
||||||
type: 'number',
|
|
||||||
description: 'Port to connect to',
|
|
||||||
default: 6379,
|
|
||||||
errorMessage: {
|
|
||||||
type: 'Redis property "socket.port" should be a number.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
required: ['host', 'port'],
|
|
||||||
errorMessage: {
|
|
||||||
type: 'Redis property "socket" should be an object.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
username: {
|
|
||||||
type: 'string',
|
|
||||||
description: 'ACL username',
|
|
||||||
errorMessage: {
|
|
||||||
type: 'Redis property "username" should be a string.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
type: 'string',
|
|
||||||
description: 'ACL password',
|
|
||||||
errorMessage: {
|
|
||||||
type: 'Redis property "password" should be a string.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
database: {
|
|
||||||
type: 'number',
|
|
||||||
description: 'Database number to connect to',
|
|
||||||
minimum: 0,
|
|
||||||
errorMessage: {
|
|
||||||
type: 'Redis property "database" should be a number.',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
oneOf: [
|
require: ['connection'],
|
||||||
{
|
|
||||||
required: ['url'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: ['socket'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
errorMessage: {
|
errorMessage: {
|
||||||
type: 'Redis connection properties should be an object.',
|
type: 'Redis connection properties should be an object.',
|
||||||
oneOf:
|
|
||||||
'Redis connection should have required property "url" or "socket.host" and "socket.port".',
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user