Browse Source

Implements a first attempt at a way to extract validation rules from the database schema.

master
Zed A. Shaw 2 weeks ago
parent
commit
698c476fab
  1. 12
      api/register.js
  2. 55
      lib/ormish.js
  3. 14
      tests/models/user.js

12
api/register.js

@ -2,14 +2,14 @@ import { User, Site } from "../lib/models.js";
import * as queues from "../lib/queues.js";
import { API } from "../lib/api.js";
const rules = {
email: 'required|email',
full_name: 'required',
const rules = User.validation({
email: '',
full_name: '',
initials: 'required|alpha|max:3',
password: 'required|same:password_repeat',
password_repeat: 'required',
password_repeat: 'required|same:password',
password: '',
tos_agree: 'required|boolean|accepted',
}
})
export const post = async (req, res) => {
const api = new API(req, res);

55
lib/ormish.js

@ -48,6 +48,61 @@ export class Model {
return this.constructor.table_name;
}
/**
* Returns an object of basic rules meant for lib/api.js:validate
* based on what's in the database. It's meant to be an easy to
* pass in starter which you can augment. It expects a set of rules
* with keys you want configured. Any key that's set to an empty string ""
* will be filled in with a minimum rule to match the database schema.
*
* It's designed to be called once at the top of an api/ handler to get
* a basic set of rules. You could also run it to print out the rules then
* simply write the rules directly where you need them.
*
* @param rules {Object} - rules specifier
*/
static validation(rules) {
assert(rules, "rules parameter is required and will be modified");
for(let [key, opts] of Object.entries(this.schema)) {
if(rules[key] === "") {
switch(opts.type) {
case "varchar": // fallthrough
case "text":
// some databases have an email type but we'll also look for ones named email
if(key === "email") {
rules[key] = "required|email";
} else {
rules[key] = "required|string";
}
if(opts.maxLength) {
rules[key] += `|min:0|max:${opts.maxLength}`;
}
break;
case "boolean":
rules[key] = "required|boolean";
break;
case "integer":
case "float":
rules[key] = "required|numeric";
break;
case "datetime":
rules[key] = "required|date";
break;
case "email":
// not all databases have this
rules[key] = "required|email";
break;
default:
rules[key] = "required";
}
}
}
return rules;
}
async destroy() {
assert(this.table_name !== undefined, "You must set class variable table_name.");

14
tests/models/user.js

@ -2,6 +2,20 @@ import test from "ava";
import {random_user} from "../../lib/testing.js";
import { User, Payment } from "../../lib/models.js";
test('test the validation generation', (t) => {
const rules = User.validation({
email: "",
initials: "",
full_name: "",
password: "",
password_repeat: 'required_with:password|same:password',
});
t.is(rules.email, "required|email|min:0|max:255");
t.is(rules.initials, "required|string|min:0|max:255");
t.is(rules.password_repeat, 'required_with:password|same:password');
});
test('test that clean and from work', (t) => {
let user = random_user();
user.bad_key = "NOPE";

Loading…
Cancel
Save