diff options
| -rw-r--r-- | provisioning-bulkcreatedevices-html.lsp | 17 | ||||
| -rw-r--r-- | provisioning-controller.lua | 10 | ||||
| -rw-r--r-- | provisioning-editdevice-html.lsp | 10 | ||||
| -rw-r--r-- | provisioning-editdeviceparams-html.lsp | 6 | ||||
| -rw-r--r-- | provisioning-editparam-html.lsp | 17 | ||||
| -rw-r--r-- | provisioning-edittemplate-html.lsp | 21 | ||||
| -rw-r--r-- | provisioning-model.lua | 487 | ||||
| -rw-r--r-- | provisioning-scripts.lua | 15 | ||||
| -rwxr-xr-x | upgradeprovisioning | 2 | 
9 files changed, 388 insertions, 197 deletions
diff --git a/provisioning-bulkcreatedevices-html.lsp b/provisioning-bulkcreatedevices-html.lsp index 0f0e45f..71ab322 100644 --- a/provisioning-bulkcreatedevices-html.lsp +++ b/provisioning-bulkcreatedevices-html.lsp @@ -3,6 +3,23 @@ htmlviewfunctions = require("htmlviewfunctions")  html = require("acf.html")  %> +<script type="text/javascript"> +	if (typeof jQuery == 'undefined') { +		document.write('<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix) %>/js/jquery-latest.js"><\/script>'); +	} +</script> + +<script type="text/javascript"> +        $(document).ready(function() { +		$("[id=<%= page_info.action %>]").submit(function(event){ +			if ($(this).find("#notifydevices").is(":checked")) { +				return confirm("Are you sure you want to notify affected devices? This might cause a reboot."); +			} +			return true; +		}); +        }); +</script> +  <% htmlviewfunctions.displayitem(form, page_info) %>  <% diff --git a/provisioning-controller.lua b/provisioning-controller.lua index 96ab26f..bcbd52f 100644 --- a/provisioning-controller.lua +++ b/provisioning-controller.lua @@ -11,7 +11,7 @@ mymodule.edittemplate = function( self )  end  mymodule.createtemplate = function( self ) -	return self.handle_form(self, self.model.get_template, self.model.create_template, self.clientdata, "Create", "Create Template", "Template Created") +	return self.handle_form(self, self.model.get_new_template, self.model.create_template, self.clientdata, "Create", "Create Template", "Template Created")  end  mymodule.deletetemplate = function( self ) @@ -27,7 +27,7 @@ mymodule.editclassgroup = function( self )  end  mymodule.createclassgroup = function( self ) -	return self.handle_form(self, self.model.get_class_group, self.model.create_class_group, self.clientdata, "Create", "Create Class Group", "Parameter Class Created") +	return self.handle_form(self, self.model.get_new_class_group, self.model.create_class_group, self.clientdata, "Create", "Create Class Group", "Parameter Class Created")  end  mymodule.deleteclassgroup = function( self ) @@ -43,7 +43,7 @@ mymodule.editclass = function( self )  end  mymodule.createclass = function( self ) -	return self.handle_form(self, self.model.get_class, self.model.create_class, self.clientdata, "Create", "Create Class", "Class Created") +	return self.handle_form(self, self.model.get_new_class, self.model.create_class, self.clientdata, "Create", "Create Class", "Class Created")  end  mymodule.deleteclass = function( self ) @@ -63,7 +63,7 @@ mymodule.editgroup = function( self )  end  mymodule.creategroup = function( self ) -	return self.handle_form(self, self.model.get_group, self.model.create_group, self.clientdata, "Create", "Create Parameter Group", "Parameter Group Created") +	return self.handle_form(self, self.model.get_new_group, self.model.create_group, self.clientdata, "Create", "Create Parameter Group", "Parameter Group Created")  end  mymodule.deletegroup = function(self ) @@ -79,7 +79,7 @@ mymodule.editparam = function( self )  end  mymodule.createparam = function( self ) -	return self.handle_form(self, self.model.get_param, self.model.create_param, self.clientdata, "Create", "Create Parameter", "Parameter Created") +	return self.handle_form(self, self.model.get_new_param, self.model.create_param, self.clientdata, "Create", "Create Parameter", "Parameter Created")  end  mymodule.deleteparam = function( self ) diff --git a/provisioning-editdevice-html.lsp b/provisioning-editdevice-html.lsp index fe375aa..85161b7 100644 --- a/provisioning-editdevice-html.lsp +++ b/provisioning-editdevice-html.lsp @@ -29,6 +29,12 @@ html = require("acf.html")          $(document).ready(function() {  		$(".deletedevice").click(function(){ return confirm("Are you sure you want to delete this device?")}); +		$("[id=<%= page_info.action %>]").submit(function(event){ +			if ($(this).find("#notifydevices").is(":checked")) { +				return confirm("Are you sure you want to notify affected devices? This might cause a reboot."); +			} +			return true; +		});          });  </script> @@ -50,7 +56,9 @@ html = require("acf.html")  		form.value.device_id.readonly = "true"  	elseif page_info.action == "duplicatedevice" then  		form.value.classes = nil -	else +		form.value.notifydevices.value = false +		form.value.notifydevices.type = "hidden" +	elseif form.value.device_id then  		form.value.device_id.type = "hidden"  	end  	htmlviewfunctions.displayitem(form, page_info) diff --git a/provisioning-editdeviceparams-html.lsp b/provisioning-editdeviceparams-html.lsp index 9229264..2ee0374 100644 --- a/provisioning-editdeviceparams-html.lsp +++ b/provisioning-editdeviceparams-html.lsp @@ -91,6 +91,12 @@ end          $(document).ready(function() {  		$(".deletedevice").click(function(){ return confirm("Are you sure you want to delete this device?")}); +		$("[id=<%= page_info.action %>]").submit(function(event){ +			if ($(this).find("#notifydevices").is(":checked")) { +				return confirm("Are you sure you want to notify affected devices? This might cause a reboot."); +			} +			return true; +		});  		$(".groupdefaultoverride").siblings().select("contains('Default:')").addClass("error");  		hideunuseddivs();          }); diff --git a/provisioning-editparam-html.lsp b/provisioning-editparam-html.lsp index b154766..96b76f1 100644 --- a/provisioning-editparam-html.lsp +++ b/provisioning-editparam-html.lsp @@ -3,6 +3,23 @@ htmlviewfunctions = require("htmlviewfunctions")  html = require("acf.html")  %> +<script type="text/javascript"> +	if (typeof jQuery == 'undefined') { +		document.write('<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix) %>/js/jquery-latest.js"><\/script>'); +	} +</script> + +<script type="text/javascript"> +        $(document).ready(function() { +		$("[id=<%= page_info.action %>]").submit(function(event){ +			if ($(this).find("#notifydevices").is(":checked")) { +				return confirm("Are you sure you want to notify affected devices? This might cause a reboot."); +			} +			return true; +		}); +        }); +</script> +  <%  	htmlviewfunctions.displaycommandresults({"editoptions"}, session, true)  	htmlviewfunctions.displayitem(form, page_info) diff --git a/provisioning-edittemplate-html.lsp b/provisioning-edittemplate-html.lsp index 0ef5bc2..56d3446 100644 --- a/provisioning-edittemplate-html.lsp +++ b/provisioning-edittemplate-html.lsp @@ -2,8 +2,26 @@  <% htmlviewfunctions = require("htmlviewfunctions") %>  <% html = require("acf.html") %> +<script type="text/javascript"> +	if (typeof jQuery == 'undefined') { +		document.write('<script type="text/javascript" src="<%= html.html_escape(page_info.wwwprefix) %>/js/jquery-latest.js"><\/script>'); +	} +</script> + +<script type="text/javascript"> +        $(document).ready(function() { +		$("[id=<%= page_info.action %>]").submit(function(event){ +			if ($(this).find("#notifydevices").is(":checked")) { +				return confirm("Are you sure you want to notify affected devices? This might cause a reboot."); +			} +			return true; +		}); +        }); +</script> +  <% local header_level = htmlviewfunctions.displaysectionstart(form, page_info) %>  <% htmlviewfunctions.displayformstart(form, page_info) %> +<% htmlviewfunctions.displayformitem(form.value.notifydevices, "notifydevices") %>  <% local header_level2 = htmlviewfunctions.displaysectionstart(cfe({label="Template Details"}), page_info, htmlviewfunctions.incrementheader(header_level)) %>  <%  if page_info.action == "edittemplate" then @@ -15,6 +33,7 @@ htmlviewfunctions.displayformitem(form.value.seq, "seq")  %>  <% htmlviewfunctions.displaysectionend(header_level2) %> +<% if form.value.filecontent then %>  <% htmlviewfunctions.displaysectionstart(cfe({label="File Content"}), page_info, header_level2) %>  <textarea name="filecontent">  <%= html.html_escape(form.value.filecontent.value) %> @@ -22,5 +41,7 @@ htmlviewfunctions.displayformitem(form.value.seq, "seq")  <% htmlviewfunctions.displayinfo(form.value.filecontent) %>  <% htmlviewfunctions.displaysectionend(header_level2) %> +<% end %> +  <% htmlviewfunctions.displayformend(form) %>  <% htmlviewfunctions.displaysectionend(header_level) %> diff --git a/provisioning-model.lua b/provisioning-model.lua index 5787daa..6d3dc59 100644 --- a/provisioning-model.lua +++ b/provisioning-model.lua @@ -321,11 +321,33 @@ local checkgroupdefaultoverride = function(device_id)  	return (#tmp ~= 0)  end +local add_notify_devices = function(p) +	local connected +	if not p.errtxt then +		local res, err = pcall(function() +			connected = databaseconnect(true) + +			local sql = "SELECT * FROM provisioning_params WHERE name='notifydevices'" +			local tmp = getselectresponse(sql) +			if tmp and #tmp ~= 0 then +				p.value.notifydevices = tmp[1] +			end + +			if connected then databasedisconnect() end +		end) +		if not res and err then +			handlesqlexception(connected, err) +			p.errtxt = err +		end +	end +	return p +end +  -- This function is used by scripts, do not change prototype  local get_device = function(device_id, create)  	local connected  	local retval = {} -	retval.device_id = cfe({value=device_id or "", label="Device ID", seq=1}) +	if not create then retval.device_id = cfe({value=device_id or "", label="Device ID", readonly=true, seq=0}) end  	retval.classes = cfe({type="group", value={}, label="Classes", seq=2})  	local errtxt  	local res, err = pcall(function() @@ -595,45 +617,54 @@ mymodule.list_templates = function()  	return cfe({ type="structure", value=retval, label="Templates", errtxt=errtxt })  end +mymodule.get_new_template = function(self, clientdata) +	local retval = cfe({ type="group", value={}, label="Provisioning Template" }) +	retval.value.filename = cfe({label="File Name", descr="Must be in "..baseurl, seq=1}) +	retval.value.label = cfe({label="Label", seq=2}) +	retval.value.seq = cfe({label="Sequence", seq=3}) +	self.handle_clientdata(retval, clientdata) +	return retval +end +  mymodule.get_template = function(self, clientdata)  	local connected -	clientdata = clientdata or {} -	local filename = clientdata.filename -	local retval = {} -	if filename and not string.match(filename, "/") then +	local retval = mymodule.get_new_template(self, clientdata) + +	local filename = retval.value.filename.value +	if filename~="" and not string.match(filename, "/") then  		filename = baseurl .. filename +		retval.value.filename.value = filename  	end -	retval.filename = cfe({value=filename or "", label="File Name", descr="Must be in "..baseurl, seq=1}) -	retval.label = cfe({label="Label", seq=2}) -	retval.seq = cfe({label="Sequence", seq=3}) -	local errtxt -	if filename and filename ~= "" then +	if filename ~= "" then  	        local res, err = pcall(function()  			connected = databaseconnect(true)  			local sql = "SELECT * FROM provisioning_options WHERE param_id=(SELECT param_id FROM provisioning_params WHERE name = 'template') AND value='"..provdb.escape(filename).."' ORDER BY seq ASC, label ASC, value ASC"  			local tmp = getselectresponse(sql)  			if tmp and #tmp > 0 then  				for n,v in pairs(tmp[1]) do -					if n == "value" then -						retval.filename.value = v -					elseif retval[n] then -						retval[n].value = v +					if retval.value[n] then +						retval.value[n].value = v  					end  				end +			else +				retval.errtxt = "Template does not exist"  			end  			if connected then databasedisconnect() end + +			local filedetails = modelfunctions.getfiledetails(retval.value.filename.value, function(filename) return validator.is_valid_filename(filename, baseurl) end) +			for i,n in ipairs({"filecontent", "size", "mtime"}) do +				retval.value[n] = filedetails.value[n] +			end  		end)  		if not res and err then  			handlesqlexception(connected, err) -			errtxt = err +			retval.errtxt = err  		end -	end -	local filedetails = modelfunctions.getfiledetails(retval.filename.value, function(filename) return validator.is_valid_filename(filename, baseurl) end) -	for i,n in ipairs({"filecontent", "size", "mtime"}) do -		retval[n] = filedetails.value[n] +	else +		retval.errtxt = "Template does not exist"  	end -	return cfe({ type="group", value=retval, label="Provisioning Template", errtxt=errtxt }) +	return add_notify_devices(retval)  end  mymodule.create_template = function(self, template, action) @@ -682,7 +713,9 @@ mymodule.update_template = function(self, template, action, create)  				end  				runsqlcommand(sql) -				fs.write_file(template.value.filename.value, string.gsub(format.dostounix(template.value.filecontent.value), "\n+$", "")) +				if template.value.filecontent then +					fs.write_file(template.value.filename.value, string.gsub(format.dostounix(template.value.filecontent.value), "\n+$", "")) +				end  			end  			if connected then databasedisconnect() end  		end) @@ -766,39 +799,48 @@ mymodule.list_class_groups = function()  	return cfe({ type="structure", value=retval, label="Class Groups", errtxt=errtxt })  end +mymodule.get_new_class_group = function(self, clientdata) +	local retval = cfe({ type="group", value={}, label="Provisioning Class Group" }) +	retval.value.name = cfe({label="Name", seq=2}) +	retval.value.label = cfe({label="Label", seq=3}) +	retval.value.seq = cfe({label="Sequence", seq=4}) +	self.handle_clientdata(retval, clientdata) +	return retval +end +  mymodule.get_class_group = function(self, clientdata)  	local connected -	clientdata = clientdata or {} -	local class_group_id = clientdata.class_group_id -	local retval = {} -	retval.class_group_id = cfe({value=class_group_id or "", label="Class Group ID", readonly=true, seq=1}) -	retval.name = cfe({label="Name", seq=2}) -	retval.label = cfe({label="Label", seq=3}) -	retval.seq = cfe({label="Sequence", seq=4}) -	local errtxt -	local res, err = pcall(function() -		connected = databaseconnect(true) -		if class_group_id and class_group_id ~= "" then +	local retval = mymodule.get_new_class_group(self, clientdata) +	retval.value.class_group_id = cfe({label="Class Group ID", seq=0}) +	self.handle_clientdata(retval, clientdata) +	retval.value.class_group_id.readonly=true + +	local class_group_id = retval.value.class_group_id.value +	if class_group_id ~= "" then +		local res, err = pcall(function() +			connected = databaseconnect(true)  			sql = "SELECT * FROM provisioning_class_groups WHERE class_group_id='"..provdb.escape(class_group_id).."'"  			tmp = getselectresponse(sql)  			if tmp and #tmp > 0 then  				for n,v in pairs(tmp[1]) do -					if retval[n] then -						retval[n].value = v +					if retval.value[n] then +						retval.value[n].value = v  					end  				end +			else +				retval.errtxt = "Class Group does not exist"  			end -		else -			retval.class_group_id = nil +			if connected then databasedisconnect() end +		end) +		if not res and err then +			handlesqlexception(connected, err) +			retval.errtxt = err  		end -		if connected then databasedisconnect() end -	end) -	if not res and err then -		handlesqlexception(connected, err) -		errtxt = err +	else +		retval.errtxt = "Class Group does not exist"  	end -	return cfe({ type="group", value=retval, label="Provisioning Class Group", errtxt=errtxt }) +	return add_notify_devices(retval)  end  mymodule.create_class_group = function(self, group, action) @@ -925,66 +967,94 @@ mymodule.list_classes = function()  	return cfe({ type="structure", value=retval, label="Classes", errtxt=errtxt })  end -mymodule.get_class = function(self, clientdata) +mymodule.get_new_class = function(self, clientdata)  	local connected -	clientdata = clientdata or {} -	local class_id = clientdata.class_id -	local retval = {} -	retval.class_id = cfe({value=class_id or "", label="Class ID", readonly=true, seq=1}) -	retval.class_group_id = cfe({type="select", label="Class Group", option={}, seq=2}) -	retval.label = cfe({label="Label", seq=3}) -	retval.seq = cfe({label="Sequence", seq=4}) -	retval.groups = cfe({type="group", value={}, label="Parameter Groups", seq=5}) -	local errtxt +	local retval = cfe({ type="group", value={}, label="Provisioning Class" }) +	retval.value.class_group_id = cfe({type="select", label="Class Group", option={}, seq=2}) +	retval.value.label = cfe({label="Label", seq=3}) +	retval.value.seq = cfe({label="Sequence", seq=4}) +	retval.value.groups = cfe({type="group", value={}, label="Parameter Groups", seq=5}) +  	local res, err = pcall(function() -		local groups = {}  		connected = databaseconnect(true) -		if class_id and class_id ~= "" then -			local sql = "SELECT * FROM provisioning_classes WHERE class_id='"..provdb.escape(class_id).."'" -			local tmp = getselectresponse(sql) -			if tmp and #tmp > 0 then -				for n,v in pairs(tmp[1]) do -					if retval[n] then -						retval[n].value = v -					end -				end -			end -			-- Now, get the class-to-paramgroup mappings -			sql = "SELECT group_id FROM classes_to_param_groups WHERE class_id='"..provdb.escape(class_id).."'" -			tmp = getselectresponse(sql) -			for i,g in ipairs(tmp) do -				groups[g.group_id] = true -			end -		else -			retval.class_id = nil -		end  		-- Get the class_group_id options  		sql = "SELECT * from provisioning_class_groups ORDER BY seq ASC, label ASC"  		tmp = getselectresponse(sql)  		for i,g in ipairs(tmp) do -			retval.class_group_id.option[#retval.class_group_id.option + 1] = {value=g.class_group_id, label=g.label} +			retval.value.class_group_id.option[#retval.value.class_group_id.option + 1] = {value=g.class_group_id, label=g.label}  		end  		-- Finally, get the paramgroup options  		sql = "SELECT group_id, name, label FROM provisioning_groups ORDER BY seq ASC, name ASC"  		tmp = getselectresponse(sql)  		for i,g in ipairs(tmp) do -			if not retval.groups.value[g.name] then -				retval.groups.value[g.name] = cfe({type="select", label=g.name, option={{value="", label=""}}, seq=i}) +			if not retval.value.groups.value[g.name] then +				retval.value.groups.value[g.name] = cfe({type="select", label=g.name, option={{value="", label=""}}, seq=i})  			end -			local group = retval.groups.value[g.name] +			local group = retval.value.groups.value[g.name]  			group.option[#group.option + 1] = {value=g.group_id, label=g.label} -			if groups[g.group_id] then -				group.value = g.group_id -			end  		end  		if connected then databasedisconnect() end  	end)  	if not res and err then  		handlesqlexception(connected, err) -		errtxt = err +		retval.errtxt = err  	end -	return cfe({ type="group", value=retval, label="Provisioning Class", errtxt=errtxt }) +	self.handle_clientdata(retval, clientdata) +	return retval +end + +mymodule.get_class = function(self, clientdata) +	local connected +	local retval = mymodule.get_new_class(self, clientdata) +	retval.value.class_id = cfe({label="Class ID", seq=0}) +	self.handle_clientdata(retval, clientdata) +	retval.value.class_id.readonly=true + +	local class_id = retval.value.class_id.value +	if class_id ~= "" then +		local res, err = pcall(function() +			local groups = {} +			connected = databaseconnect(true) +			local sql = "SELECT * FROM provisioning_classes WHERE class_id='"..provdb.escape(class_id).."'" +			local tmp = getselectresponse(sql) +			if tmp and #tmp > 0 then +				for n,v in pairs(tmp[1]) do +					if retval.value[n] then +						retval.value[n].value = v +					end +				end + +				-- Now, get the class-to-paramgroup mappings +				sql = "SELECT group_id FROM classes_to_param_groups WHERE class_id='"..provdb.escape(class_id).."'" +				tmp = getselectresponse(sql) +				for i,g in ipairs(tmp) do +					groups[g.group_id] = true +				end + +				-- Loop through the groups and options to mark the mappings +				for n,g in pairs(retval.value.groups.value) do +					for i,o in ipairs(g.option) do +						if groups[o.value] then +							g.value = o.value +							break +						end +					end +				end +			else +				retval.errtxt = "Class does not exist" +			end +			if connected then databasedisconnect() end +		end) +		if not res and err then +			handlesqlexception(connected, err) +			retval.errtxt = err +		end +	else +		retval.errtxt = "Class does not exist" +	end + +	return add_notify_devices(retval)  end  mymodule.create_class = function(self, class, action) @@ -1119,29 +1189,26 @@ mymodule.list_groups = function()  	return cfe({ type="structure", value=retval, label="Parameter Groups", errtxt=errtxt })  end -mymodule.get_group = function(self, clientdata) +mymodule.get_new_group = function(self, clientdata)  	local connected -	clientdata = clientdata or {} -	local group_id = clientdata.group_id -	local retval = {} -	retval.group_id = cfe({value=group_id or "", label="Group ID", readonly=true, seq=1}) -	retval.name = cfe({label="Name", seq=2}) -	retval.label = cfe({label="Label", seq=3}) -	retval.seq = cfe({label="Sequence", seq=4}) -	retval.params = cfe({type="multi", value={}, label="Parameters", option={}, descr="Each selected parameter will be included in the group", seq=5}) -	retval.editable = cfe({type="multi", value={}, label="Editable Parameters", option={}, descr="Each selected parameter will be user editable", seq=6}) -	retval.override = cfe({type="multi", value={}, label="Overridden Parameters", option={}, descr="Each selected parameter will override the parameter default from the group defaults", seq=7}) -	retval.defaults = cfe({type="group", value={}, label="Parameter Defaults", seq=8}) -	local errtxt +	local retval = cfe({ type="group", value={}, label="Provisioning Parameter Group" }) +	retval.value.name = cfe({label="Name", seq=2}) +	retval.value.label = cfe({label="Label", seq=3}) +	retval.value.seq = cfe({label="Sequence", seq=4}) +	retval.value.params = cfe({type="multi", value={}, label="Parameters", option={}, descr="Each selected parameter will be included in the group", seq=5}) +	retval.value.editable = cfe({type="multi", value={}, label="Editable Parameters", option={}, descr="Each selected parameter will be user editable", seq=6}) +	retval.value.override = cfe({type="multi", value={}, label="Overridden Parameters", option={}, descr="Each selected parameter will override the parameter default from the group defaults", seq=7}) +	retval.value.defaults = cfe({type="group", value={}, label="Parameter Defaults", seq=8}) +  	local res, err = pcall(function()  		connected = databaseconnect(true) -		-- First, let's get all the parameters to set up the params.options and defaults +		-- Get all the parameters to set up the params.options and defaults  		local sql = "SELECT * FROM provisioning_params ORDER BY seq ASC, name ASC"  		local tmp = getselectresponse(sql)  		for i,p in ipairs(tmp) do -			retval.params.option[#retval.params.option + 1] = {value=p.param_id, label=p.label} -			retval.editable.option[#retval.editable.option + 1] = {value=p.param_id, label=p.label} -			retval.override.option[#retval.override.option + 1] = {value=p.param_id, label=p.label} +			retval.value.params.option[#retval.value.params.option + 1] = {value=p.param_id, label=p.label} +			retval.value.editable.option[#retval.value.editable.option + 1] = {value=p.param_id, label=p.label} +			retval.value.override.option[#retval.value.override.option + 1] = {value=p.param_id, label=p.label}  			p.seq = i  			if p.type == "select" then  				sql = "SELECT * FROM provisioning_options WHERE param_id='"..provdb.escape(p.param_id).."' ORDER BY seq ASC" @@ -1151,46 +1218,70 @@ mymodule.get_group = function(self, clientdata)  				p.value = (p.value == "true")  			end  			p.default = p.value -			retval.defaults.value[p.param_id] = p +			retval.value.defaults.value[p.param_id] = p  		end -		if group_id and group_id ~= "" then +		if connected then databasedisconnect() end +	end) +	if not res and err then +		handlesqlexception(connected, err) +		retval.errtxt = err +	end + +	self.handle_clientdata(retval, clientdata) +	return retval +end + +mymodule.get_group = function(self, clientdata) +	local connected +	local retval = mymodule.get_new_group(self, clientdata) +	retval.value.group_id = cfe({value=group_id or "", label="Group ID", seq=0}) +	self.handle_clientdata(retval, clientdata) +	retval.value.group_id.readonly=true + +	local group_id = retval.value.group_id.value +	if group_id ~= "" then +		local res, err = pcall(function() +			connected = databaseconnect(true)  			sql = "SELECT * FROM provisioning_groups WHERE group_id='"..provdb.escape(group_id).."'"  			tmp = getselectresponse(sql)  			if tmp and #tmp > 0 then  				for n,v in pairs(tmp[1]) do -					if retval[n] then -						retval[n].value = v +					if retval.value[n] then +						retval.value[n].value = v  					end  				end -			end -			-- Now, get the paramgroup-to-param mappings -			sql = "SELECT * FROM param_groups_to_params WHERE group_id='"..provdb.escape(group_id).."'" -			tmp = getselectresponse(sql) -			for i,p in ipairs(tmp) do -				retval.params.value[#retval.params.value + 1] = p.param_id -				if (p.editable == "t") then -					retval.editable.value[#retval.editable.value + 1] = p.param_id -				end -				if p.value then -					retval.override.value[#retval.override.value + 1] = p.param_id -					if retval.defaults.value[p.param_id].type == "boolean" then -						retval.defaults.value[p.param_id].value = (p.value == "true") -					else -						retval.defaults.value[p.param_id].value = p.value + +				-- Now, get the paramgroup-to-param mappings +				sql = "SELECT * FROM param_groups_to_params WHERE group_id='"..provdb.escape(group_id).."'" +				tmp = getselectresponse(sql) +				for i,p in ipairs(tmp) do +					retval.value.params.value[#retval.value.params.value + 1] = p.param_id +					if (p.editable == "t") then +						retval.value.editable.value[#retval.value.editable.value + 1] = p.param_id +					end +					if p.value then +						retval.value.override.value[#retval.value.override.value + 1] = p.param_id +						if retval.value.defaults.value[p.param_id].type == "boolean" then +							retval.value.defaults.value[p.param_id].value = (p.value == "true") +						else +							retval.value.defaults.value[p.param_id].value = p.value +						end  					end  				end +			else +				retval.errtxt = "Group does not exist"  			end -		else -			retval.group_id = nil +			if connected then databasedisconnect() end +		end) +		if not res and err then +			handlesqlexception(connected, err) +			retval.errtxt = err  		end -		if connected then databasedisconnect() end -	end) -	if not res and err then -		handlesqlexception(connected, err) -		errtxt = err +	else +		retval.errtxt = "Group does not exist"  	end -	return cfe({ type="group", value=retval, label="Provisioning Parameter Group", errtxt=errtxt }) +	return add_notify_devices(retval)  end  mymodule.create_group = function(self, group, action) @@ -1367,44 +1458,54 @@ mymodule.list_params = function()  	return cfe({ type="structure", value=retval, label="Parameters", errtxt=errtxt })  end +mymodule.get_new_param = function(self, clientdata) +	local retval = cfe({ type="group", value={}, label="Provisioning Parameter" }) +	retval.value.name = cfe({label="Name", seq=2}) +	retval.value.type = cfe({type="select", label="Type", option={"text", "boolean", "select"}, seq=3}) +	retval.value.label = cfe({label="Label", seq=4}) +	retval.value.descr = cfe({label="Description", seq=5}) +	retval.value.value = cfe({label="Default Value", descr="Warning, this value is not validated", seq=6}) +	retval.value.regexp = cfe({label="Regular Expression", descr="Lua regular expression for validating the text parameter value", seq=7}) +	retval.value.validate = cfe({type="longtext", label="Validation Code", descr="Lua code to validate the parameter value. Returns updated value and error text. Not used to validate group defaults.", seq=8}) +	retval.value.seq = cfe({label="Sequence", seq=9}) + +	self.handle_clientdata(retval, clientdata) +	return retval +end +  mymodule.get_param = function(self, clientdata)  	local connected -	clientdata = clientdata or {} -	local param_id = clientdata.param_id -	local retval = {} -	retval.param_id = cfe({value=param_id or "", label="Param ID", readonly=true, seq=1}) -	retval.name = cfe({label="Name", seq=2}) -	retval.type = cfe({type="select", label="Type", option={"text", "boolean", "select"}, seq=3}) -	retval.label = cfe({label="Label", seq=4}) -	retval.descr = cfe({label="Description", seq=5}) -	retval.value = cfe({label="Default Value", descr="Warning, this value is not validated", seq=6}) -	retval.regexp = cfe({label="Regular Expression", descr="Lua regular expression for validating the text parameter value", seq=7}) -	retval.validate = cfe({type="longtext", label="Validation Code", descr="Lua code to validate the parameter value. Returns updated value and error text. Not used to validate group defaults.", seq=8}) -	retval.seq = cfe({label="Sequence", seq=9}) -	local errtxt -	local res, err = pcall(function() -		connected = databaseconnect(true) -		if param_id and param_id ~= "" then +	local retval = mymodule.get_new_param(self, clientdata) +	retval.value.param_id = cfe({value=param_id or "", label="Param ID", seq=0}) +	self.handle_clientdata(retval, clientdata) +	retval.value.param_id.readonly=true + +	local param_id = retval.value.param_id.value +	if param_id ~= "" then +		local res, err = pcall(function() +			connected = databaseconnect(true)  			sql = "SELECT * FROM provisioning_params WHERE param_id='"..provdb.escape(param_id).."'"  			tmp = getselectresponse(sql)  			if tmp and #tmp > 0 then  				for n,v in pairs(tmp[1]) do -					if retval[n] then -						retval[n].value = v +					if retval.value[n] then +						retval.value[n].value = v  					end  				end +			else +				retval.errtxt = "Parameter does not exist"  			end -		else -			retval.param_id = nil +			if connected then databasedisconnect() end +		end) +		if not res and err then +			handlesqlexception(connected, err) +			retval.errtxt = err  		end -		if connected then databasedisconnect() end -	end) -	if not res and err then -		handlesqlexception(connected, err) -		errtxt = err +	else +		retval.errtxt = "Parameter does not exist"  	end -	return cfe({ type="group", value=retval, label="Provisioning Parameter", errtxt=errtxt }) +	return add_notify_devices(retval)  end  mymodule.create_param = function(self, param, action) @@ -1640,13 +1741,17 @@ mymodule.list_devices = function(self, clientdata)  end  mymodule.get_existing_device = function(self, clientdata) -	clientdata = clientdata or {} -	return get_device(clientdata.device_id, false) +	local tmp = cfe({ type="group", value={device_id = cfe()} }) +	self.handle_clientdata(tmp, clientdata) +	retval = get_device(tmp.value.device_id.value, false) +	self.handle_clientdata(retval, clientdata) +	return add_notify_devices(retval)  end  mymodule.get_new_device = function(self, clientdata) -	clientdata = clientdata or {} -	return get_device(clientdata.device_id, true) +	retval = get_device(nil, true) +	self.handle_clientdata(retval, clientdata) +	return retval  end  mymodule.create_device = function(self, device, action) @@ -1678,25 +1783,29 @@ mymodule.update_device = function(self, device, action, create)  				end  			end  			if success then -				if not saved_devices[device.value.device_id.value] then get_device(device.value.device_id.value) end -				if not saved_device_params[device.value.device_id.value] then get_device_params(device.value.device_id.value) end - +				local device_id  				if create then  					sql = "SELECT nextval('provisioning_device_seq')"  					local tmp = getselectresponse(sql)  					if tmp and #tmp>0 then -						device.value.device_id.value = tmp[1].nextval +						device_id = tmp[1].nextval +						-- Add to cfe so can use to redirect to editdeviceparams +						device.value.device_id = cfe({value=device_id or "", label="Device ID", readonly=true, seq=0})  					end -					logcall("create_device "..device.value.device_id.value) +					logcall("create_device "..device_id)  				else -					logcall("update_device "..device.value.device_id.value) +					device_id = device.value.device_id.value +					if not saved_devices[device_id] then get_device(device_id) end +					if not saved_device_params[device_id] then get_device_params(device_id) end + +					logcall("update_device "..device_id)  				end -				sql = "DELETE FROM devices_to_classes WHERE device_id='"..provdb.escape(device.value.device_id.value).."'" +				sql = "DELETE FROM devices_to_classes WHERE device_id='"..provdb.escape(device_id).."'"  				runsqlcommand(sql)  				-- Insert the device to class entries  				for n,c in pairs(device.value.classes.value) do  					if c.value ~= "" then -						sql = "INSERT INTO devices_to_classes VALUES('"..provdb.escape(device.value.device_id.value).."', '"..provdb.escape(c.value).."')" +						sql = "INSERT INTO devices_to_classes VALUES('"..provdb.escape(device_id).."', '"..provdb.escape(c.value).."')"  						runsqlcommand(sql)  					end  				end @@ -1704,8 +1813,8 @@ mymodule.update_device = function(self, device, action, create)  				device.descr = "Device Created"  				-- Notify the device that its params might have changed (this will also validate) -				local s = saved_device_params[device.value.device_id.value] -				local r = set_device_params(get_device_params(device.value.device_id.value, false), false) +				local s = saved_device_params[device_id] +				local r = set_device_params(get_device_params(device_id, false), false)  				if r.errtxt then  					if create then  						device.descr = device.descr.."\nERROR: Failed to update params\n"..r:print_errtxt() @@ -1714,9 +1823,9 @@ mymodule.update_device = function(self, device, action, create)  					end  				end -				callscript(updatedevicescriptfile, device, saved_devices[device.value.device_id.value], r, s) +				callscript(updatedevicescriptfile, device, saved_devices[device_id], r, s) -				saved_devices[device.value.device_id.value] = device +				saved_devices[device_id] = device  			end  			if connected then databasedisconnect() end  		end) @@ -1780,21 +1889,26 @@ mymodule.delete_device = function(self, delreq)  end  mymodule.get_editable_device_params = function(self, clientdata, action) -	clientdata = clientdata or {} -	return get_device_params(clientdata.device_id, true) +	local tmp = cfe({ type="group", value={device_id = cfe()} }) +	self.handle_clientdata(tmp, clientdata) +	retval = get_device_params(tmp.value.device_id.value, true) +	self.handle_clientdata(retval, clientdata) +	return add_notify_devices(retval)  end  mymodule.get_all_device_params = function(self, clientdata, action) -	clientdata = clientdata or {} -	return get_device_params(clientdata.device_id, false) +	local tmp = cfe({ type="group", value={device_id = cfe()} }) +	self.handle_clientdata(tmp, clientdata) +	retval = get_device_params(tmp.value.device_id.value, false) +	self.handle_clientdata(retval, clientdata) +	return add_notify_devices(retval)  end  mymodule.get_class_options = function(self, clientdata) -	clientdata = clientdata or {} -	local class_id = clientdata.class_id -	local retval = {} -	retval.class_id = cfe({value=class_id or "", label="Class ID", seq=1}) -	return cfe({ type="group", value=retval, label="Provisioning Class Values" }) +	local retval = cfe({ type="group", value={}, label="Provisioning Class Values" }) +	retval.value.class_id = cfe({label="Class ID", seq=1}) +	self.handle_clientdata(retval, clientdata) +	return retval  end  mymodule.get_class_values = function(self, retval) @@ -2362,11 +2476,10 @@ mymodule.delete_request = function(self, delreq)  end  mymodule.get_request = function(self, clientdata) -	clientdata = clientdata or {} -	local mac = clientdata.mac -	local retval = {} -	retval.mac = cfe({ value=mac or "", label="MAC Address" }) -	return cfe({ type="group", value=retval, label="Create Device from Request" }) +	local retval = cfe({ type="group", value={}, label="Create Device from Request" }) +	retval.value.mac = cfe({ label="MAC Address" }) +	self.handle_clientdata(retval, clientdata) +	return add_notify_devices(retval)  end  mymodule.create_from_request = function(self, request) @@ -2425,14 +2538,20 @@ mymodule.create_from_request = function(self, request)  end  mymodule.get_bulk_create_request = function(self, clientdata) -	local retval = {} -	retval.bulkdevicedata = cfe({ type="list", value={}, label="Bulk device list", descr="List of devices as comma-separated fields (first row must contain column headers)" }) -	return cfe({ type="group", value=retval, label="Create Multiple Devices" }) +	local retval = cfe({ type="group", value={}, label="Create Multiple Devices" }) +	retval.value.bulkdevicedata = cfe({ type="list", value={}, label="Bulk device list", descr="List of devices as comma-separated fields (first row must contain column headers)" }) +	return add_notify_devices(retval)  end  mymodule.bulk_create_devices = function(self, devicelist)  	logcall("bulk_create_devices")  	local connected + +	if #devicelist.value.bulkdevicedata.value == 0 then +		devicelist.errtxt = "No devices specified" +		return devicelist +	end +  	-- To allow uploading a file, check the bulkdevicedata format  	-- Haserl will pass a temporary file name if a file is uploaded  	if #devicelist.value.bulkdevicedata.value == 1 and string.find(devicelist.value.bulkdevicedata.value[1], "^/tmp/[^.]+$") and fs.is_file(devicelist.value.bulkdevicedata.value[1]) then diff --git a/provisioning-scripts.lua b/provisioning-scripts.lua index 707348e..4f5b1c0 100644 --- a/provisioning-scripts.lua +++ b/provisioning-scripts.lua @@ -365,13 +365,13 @@ mymodule.classes_to_param_groups = {  mymodule.provisioning_groups = {  	"CREATE TABLE provisioning_groups (group_id SERIAL PRIMARY KEY, name VARCHAR(255), label VARCHAR(255) UNIQUE, seq INTEGER)",  	"CREATE INDEX groups_name_idx ON provisioning_groups (name)", -	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Linksys ATA Device', '1')", -	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Cisco ATA Device', '1')", -	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Polycom Device', '1')", -	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Snom Device', '1')", -	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Algo 8180 Device', '1')", -	"INSERT INTO provisioning_groups VALUES(default, 'device', 'CyberData Intercom Device', '1')", -	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Grandstream Device', '1')", +	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Linksys ATA Device', '5')", +	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Cisco ATA Device', '5')", +	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Polycom Device', '5')", +	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Snom Device', '5')", +	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Algo 8180 Device', '5')", +	"INSERT INTO provisioning_groups VALUES(default, 'device', 'CyberData Intercom Device', '5')", +	"INSERT INTO provisioning_groups VALUES(default, 'device', 'Grandstream Device', '5')",  	"INSERT INTO provisioning_groups VALUES(default, 'device', 'CyberData Paging Zone Controller Device', '1')",  	"INSERT INTO provisioning_groups VALUES(default, 'reg1', 'Registration 1 (Polycom)', '10')",  	"INSERT INTO provisioning_groups VALUES(default, 'reg1', 'Registration 1 (Linksys)', '10')", @@ -1233,6 +1233,7 @@ mymodule.param_groups_to_params = {  mymodule.provisioning_params = {  	"CREATE TABLE provisioning_params (param_id SERIAL PRIMARY KEY, name VARCHAR(255) UNIQUE, type VARCHAR(255), label VARCHAR(255), descr VARCHAR(255), value VARCHAR(255), seq INTEGER, regexp VARCHAR(255), validate text)",  	"CREATE INDEX params_name_idx ON provisioning_params (name)", +	"INSERT INTO provisioning_params VALUES(default, 'notifydevices', 'boolean', 'Notify Devices', 'Notify devices of changes (may cause reboot)', 'true', '1', '', null)",  	"INSERT INTO provisioning_params VALUES(default, 'mac', 'text', 'MAC Address', 'Capitalized hex digits with no punctuation', '', '1', '^%x%x%x%x%x%x%x%x%x%x%x%x$', E'local value, functions, params = ...\nvalue = string.upper(value)\nlocal others = functions.getselectresponse(\"SELECT count(*) FROM provisioning_values WHERE param_id=\\'\"..params.value.device.value.mac.param_id..\"\\' AND device_id!=\\'\"..params.value.device_id.value..\"\\' AND value=\\'\"..value..\"\\'\")\nif tonumber(others[1].count) > 0 then\n\treturn value, \"MAC Address must be unique\"\nend\nreturn value')",  	"INSERT INTO provisioning_params VALUES(default, 'template', 'select', 'Template', '', '', '2', '', null)",  	"INSERT INTO provisioning_params VALUES(default, 'registrar', 'text', 'SIP Registrar', '', '', '3', '', null)", diff --git a/upgradeprovisioning b/upgradeprovisioning index b06018f..73e046e 100755 --- a/upgradeprovisioning +++ b/upgradeprovisioning @@ -771,6 +771,8 @@ if [ "$version" -lt "12" ]; then  	psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Public Phone'), (SELECT param_id FROM provisioning_params WHERE name='receivedcallhistoryenable'), 'true', false)" provisioning  	psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Hotline'), (SELECT param_id FROM provisioning_params WHERE name='missedcallhistoryenable'), 'false', false)" provisioning  	psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Hotline'), (SELECT param_id FROM provisioning_params WHERE name='receivedcallhistoryenable'), 'false', false)" provisioning +	psql -U postgres -c "INSERT INTO provisioning_params VALUES(default, 'notifydevices', 'boolean', 'Notify Devices', 'Notify devices of changes (may cause reboot)', 'true', '1', '', null)" provisioning +	psql -U postgres -c "UPDATE provisioning_groups SET (seq)=('5') WHERE name='device' AND seq='1'" provisioning  	# database  	psql -U postgres -c "UPDATE provisioning_params SET value='12' WHERE name='databaseversion'" provisioning  | 
