type safe schema validation
This commit is contained in:
parent
a48869a2f0
commit
f7383f37da
|
@ -1,9 +1,14 @@
|
||||||
|
const handlebars = require("handlebars")
|
||||||
|
|
||||||
class Query {
|
class Query {
|
||||||
constructor(source, schema, type) {
|
constructor(source, schema, type, queryString) {
|
||||||
this.source = source
|
this.source = source
|
||||||
this.schema = schema
|
this.schema = schema
|
||||||
this.type = type
|
this.type = type
|
||||||
|
this.queryString = queryString
|
||||||
}
|
}
|
||||||
|
|
||||||
build(parameters) {}
|
build(parameters) {
|
||||||
|
this.queryStr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@
|
||||||
<Select secondary bind:value={query.queryType}>
|
<Select secondary bind:value={query.queryType}>
|
||||||
<option value={''}>Select an option</option>
|
<option value={''}>Select an option</option>
|
||||||
{#each Object.keys(config) as queryType}
|
{#each Object.keys(config) as queryType}
|
||||||
<option value={queryType}>{queryType}</option>
|
<option value={config[queryType].type}>{queryType}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
const QueryTypes = {
|
const QueryTypes = {
|
||||||
SQL: "sql",
|
SQL: "sql",
|
||||||
|
JSON: "json",
|
||||||
|
FIELDS: "fields",
|
||||||
}
|
}
|
||||||
|
|
||||||
export let query
|
export let query
|
||||||
|
@ -19,4 +21,6 @@
|
||||||
<Spacer large />
|
<Spacer large />
|
||||||
<TextArea bind:value={query.queryString} />
|
<TextArea bind:value={query.queryString} />
|
||||||
<!-- <Editor label="Query" on:change={updateQuery} value={query.queryString} /> -->
|
<!-- <Editor label="Query" on:change={updateQuery} value={query.queryString} /> -->
|
||||||
{/if}
|
{:else if query.queryType === QueryTypes.JSON}
|
||||||
|
|
||||||
|
{:else if query.queryType === QueryTypes.FIELDS}{/if}
|
||||||
|
|
|
@ -1,20 +1,7 @@
|
||||||
const handlebars = require("handlebars")
|
const handlebars = require("handlebars")
|
||||||
const Joi = require("joi")
|
|
||||||
const CouchDB = require("../../db")
|
const CouchDB = require("../../db")
|
||||||
const { generateQueryID, getQueryParams } = require("../../db/utils")
|
const { generateQueryID, getQueryParams } = require("../../db/utils")
|
||||||
const { integrations } = require("../../integrations")
|
const { integrations } = require("../../integrations")
|
||||||
const joiValidator = require("../../middleware/joi-validator")
|
|
||||||
|
|
||||||
function generateQueryValidation() {
|
|
||||||
// prettier-ignore
|
|
||||||
return joiValidator.body(Joi.object({
|
|
||||||
name: Joi.string().required(),
|
|
||||||
queryString: Joi.string().required(),
|
|
||||||
datasourceId: Joi.string().required(),
|
|
||||||
queryType: Joi.string().required(),
|
|
||||||
schema: Joi.object({}).required().unknown(true)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.fetch = async function(ctx) {
|
exports.fetch = async function(ctx) {
|
||||||
const db = new CouchDB(ctx.user.appId)
|
const db = new CouchDB(ctx.user.appId)
|
||||||
|
@ -31,13 +18,6 @@ exports.save = async function(ctx) {
|
||||||
const db = new CouchDB(ctx.user.appId)
|
const db = new CouchDB(ctx.user.appId)
|
||||||
const query = ctx.request.body
|
const query = ctx.request.body
|
||||||
|
|
||||||
//
|
|
||||||
// {
|
|
||||||
// type: "",
|
|
||||||
// query: "",
|
|
||||||
// otherStuff: ""
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!query._id) {
|
if (!query._id) {
|
||||||
query._id = generateQueryID(query.datasourceId)
|
query._id = generateQueryID(query.datasourceId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,69 @@ const Router = require("@koa/router")
|
||||||
const queryController = require("../controllers/query")
|
const queryController = require("../controllers/query")
|
||||||
const authorized = require("../../middleware/authorized")
|
const authorized = require("../../middleware/authorized")
|
||||||
const { BUILDER } = require("../../utilities/security/permissions")
|
const { BUILDER } = require("../../utilities/security/permissions")
|
||||||
|
const Joi = require("joi")
|
||||||
|
const {
|
||||||
|
PermissionLevels,
|
||||||
|
PermissionTypes,
|
||||||
|
} = require("../../utilities/security/permissions")
|
||||||
|
const joiValidator = require("../../middleware/joi-validator")
|
||||||
|
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
|
const QueryVerb = {
|
||||||
|
Create: "CREATE",
|
||||||
|
Read: "READ",
|
||||||
|
Update: "UPDATE",
|
||||||
|
Delete: "DELETE",
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateQueryValidation() {
|
||||||
|
// prettier-ignore
|
||||||
|
return joiValidator.body(Joi.object({
|
||||||
|
_id: Joi.string(),
|
||||||
|
_rev: Joi.string(),
|
||||||
|
name: Joi.string().required(),
|
||||||
|
queryString: Joi.string().required(),
|
||||||
|
datasourceId: Joi.string().required(),
|
||||||
|
parameters: Joi.array().items(Joi.object({
|
||||||
|
name: Joi.string(),
|
||||||
|
default: Joi.string()
|
||||||
|
})),
|
||||||
|
// queryVerb: Joi.string().allow(...Object.values(QueryVerb)).required(),
|
||||||
|
queryType: Joi.string().required(),
|
||||||
|
schema: Joi.object({}).required().unknown(true)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateQueryPreviewValidation() {
|
||||||
|
// prettier-ignore
|
||||||
|
return joiValidator.body(Joi.object({
|
||||||
|
query: Joi.string().required(),
|
||||||
|
datasourceId: Joi.string().required(),
|
||||||
|
parameters: Joi.object({}).required().unknown(true)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: sort out auth so apps have the right permissions
|
// TODO: sort out auth so apps have the right permissions
|
||||||
router
|
router
|
||||||
.get("/api/queries", authorized(BUILDER), queryController.fetch)
|
.get("/api/queries", authorized(BUILDER), queryController.fetch)
|
||||||
.post("/api/queries", authorized(BUILDER), queryController.save)
|
.post(
|
||||||
.post("/api/queries/preview", authorized(BUILDER), queryController.preview)
|
"/api/queries",
|
||||||
.post("/api/queries/:queryId", authorized(BUILDER), queryController.execute)
|
authorized(BUILDER),
|
||||||
|
generateQueryValidation(),
|
||||||
|
queryController.save
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
"/api/queries/preview",
|
||||||
|
authorized(BUILDER),
|
||||||
|
generateQueryPreviewValidation(),
|
||||||
|
queryController.preview
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
"/api/queries/:queryId",
|
||||||
|
authorized(PermissionTypes.QUERY, PermissionLevels.WRITE),
|
||||||
|
queryController.execute
|
||||||
|
)
|
||||||
.delete("/api/queries/:queryId", authorized(BUILDER), queryController.destroy)
|
.delete("/api/queries/:queryId", authorized(BUILDER), queryController.destroy)
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|
|
@ -29,14 +29,42 @@ const SCHEMA = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
sql: {
|
SQL: {
|
||||||
type: "sql",
|
type: "sql",
|
||||||
},
|
},
|
||||||
gui: {
|
"Simple Query": {
|
||||||
type: "config",
|
type: "fields",
|
||||||
fields: {
|
fields: {
|
||||||
something: "",
|
table: {
|
||||||
other: "",
|
type: "string",
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
condition: {
|
||||||
|
type: "options",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: "Equals",
|
||||||
|
value: "=",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Not Equals",
|
||||||
|
value: "!=",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Greater Than",
|
||||||
|
value: ">",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Less Than",
|
||||||
|
value: "<",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -58,6 +58,7 @@ exports.BUILTIN_PERMISSIONS = {
|
||||||
_id: exports.BUILTIN_PERMISSION_IDS.READ_ONLY,
|
_id: exports.BUILTIN_PERMISSION_IDS.READ_ONLY,
|
||||||
name: "Read only",
|
name: "Read only",
|
||||||
permissions: [
|
permissions: [
|
||||||
|
new Permission(PermissionTypes.QUERY, PermissionLevels.READ),
|
||||||
new Permission(PermissionTypes.TABLE, PermissionLevels.READ),
|
new Permission(PermissionTypes.TABLE, PermissionLevels.READ),
|
||||||
new Permission(PermissionTypes.VIEW, PermissionLevels.READ),
|
new Permission(PermissionTypes.VIEW, PermissionLevels.READ),
|
||||||
],
|
],
|
||||||
|
@ -66,6 +67,7 @@ exports.BUILTIN_PERMISSIONS = {
|
||||||
_id: exports.BUILTIN_PERMISSION_IDS.WRITE,
|
_id: exports.BUILTIN_PERMISSION_IDS.WRITE,
|
||||||
name: "Read/Write",
|
name: "Read/Write",
|
||||||
permissions: [
|
permissions: [
|
||||||
|
new Permission(PermissionTypes.QUERY, PermissionLevels.WRITE),
|
||||||
new Permission(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
new Permission(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
||||||
new Permission(PermissionTypes.VIEW, PermissionLevels.READ),
|
new Permission(PermissionTypes.VIEW, PermissionLevels.READ),
|
||||||
],
|
],
|
||||||
|
@ -90,6 +92,7 @@ exports.BUILTIN_PERMISSIONS = {
|
||||||
new Permission(PermissionTypes.AUTOMATION, PermissionLevels.ADMIN),
|
new Permission(PermissionTypes.AUTOMATION, PermissionLevels.ADMIN),
|
||||||
new Permission(PermissionTypes.VIEW, PermissionLevels.ADMIN),
|
new Permission(PermissionTypes.VIEW, PermissionLevels.ADMIN),
|
||||||
new Permission(PermissionTypes.WEBHOOK, PermissionLevels.READ),
|
new Permission(PermissionTypes.WEBHOOK, PermissionLevels.READ),
|
||||||
|
new Permission(PermissionTypes.QUERY, PermissionLevels.ADMIN),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue