Software /
code /
prosody
Changeset
9243:a4c52e304e6f
util.dataforms: Add support for XEP-0122: Data Forms Validation
Initially only basic validation of xs:integer
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 01 Sep 2018 03:10:09 +0200 |
parents | 9242:68694c1bd960 |
children | 9244:b3b156bd9914 |
files | spec/util_dataforms_spec.lua util/dataforms.lua |
diffstat | 2 files changed, 58 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/spec/util_dataforms_spec.lua Sat Sep 01 01:24:46 2018 +0200 +++ b/spec/util_dataforms_spec.lua Sat Sep 01 03:10:09 2018 +0200 @@ -401,5 +401,27 @@ assert.equal("hello", x:find"field/value#"); end); end); + + describe("validation", function () + local f = dataforms.new { + { + name = "number", + type = "text-single", + datatype = "xs:integer", + }, + }; + + it("works", function () + local d = f:data(f:form({number = 1})); + assert.equal(1, d.number); + end); + + it("works", function () + local d,e = f:data(f:form({number = "nan"})); + assert.not_equal(1, d.number); + assert.table(e); + assert.string(e.number); + end); + end); end);
--- a/util/dataforms.lua Sat Sep 01 01:24:46 2018 +0200 +++ b/util/dataforms.lua Sat Sep 01 03:10:09 2018 +0200 @@ -9,6 +9,7 @@ local setmetatable = setmetatable; local ipairs = ipairs; local type, next = type, next; +local tonumber = tonumber; local t_concat = table.concat; local st = require "util.stanza"; local jid_prep = require "util.jid".prep; @@ -17,6 +18,7 @@ -- luacheck: std none local xmlns_forms = 'jabber:x:data'; +local xmlns_validate = 'http://jabber.org/protocol/xdata-validate'; local form_t = {}; local form_mt = { __index = form_t }; @@ -50,6 +52,13 @@ end end + if formtype == "form" and field.datatype then + form:tag("validate", { xmlns = xmlns_validate, datatype = field.datatype }); + -- <basic/> assumed + form:up(); + end + + local value = field.value; local options = field.options; @@ -85,6 +94,10 @@ end if value ~= nil then + if type(value) == "number" then + -- TODO validate that this is ok somehow, eg check field.datatype + value = ("%g"):format(value); + end -- Add value, depending on type if field_type == "hidden" then if type(value) == "table" then @@ -141,6 +154,7 @@ end local field_readers = {}; +local data_validators = {}; function form_t.data(layout, stanza, current) local data = {}; @@ -166,7 +180,17 @@ present[field.name] = true; local reader = field_readers[field.type]; if reader then - data[field.name], errors[field.name] = reader(tag, field.required); + local value, err = reader(tag, field.required); + local validator = field.datatype and data_validators[field.datatype]; + if value ~= nil and validator then + local valid, ret = validator(value, field); + if valid then + value = ret; + else + value, err = nil, ret or field.datatype; + end + end + data[field.name], errors[field.name] = value, err; end end end @@ -265,6 +289,17 @@ return field_tag:get_child_text("value"); end +data_validators["xs:integer"] = + function (data) + local n = tonumber(data); + if not n then + return false, "not a number"; + elseif n % 1 ~= 0 then + return false, "not an integer"; + end + return true, n; + end + local function get_form_type(form) if not st.is_stanza(form) then