0
0
mirror of https://github.com/Doodle3D/doodle3d-firmware.git synced 2024-12-22 19:13:49 +01:00

Deny API access to operations that can/will interrupt printing (updating, reconfiguring network, change settings).

This commit is contained in:
Wouter R 2013-10-23 16:12:19 +02:00
parent 9e0eab1f8d
commit 628f05b682
5 changed files with 147 additions and 50 deletions

View File

@ -4,16 +4,42 @@ local settings = require('util.settings')
local printer = require('util.printer') local printer = require('util.printer')
local signin = require('network.signin') local signin = require('network.signin')
local wifi = require('network.wlanconfig') local wifi = require('network.wlanconfig')
local accessManager = require('util.access')
local printerAPI = require('rest.api.api_printer')
local M = { local M = {
isApi = true isApi = true
} }
-- TODO: this function is also defined in 2 other places, combine them (and avoid require loops)
local function operationsAccessOrFail(request, response)
if not accessManager.hasControl(request.remoteAddress) then
response:setFail("No control access")
return false
end
local rv, printerState = printerAPI.state(request, response, true)
if(rv == false) then
response:setError("Could not get printer state")
return false
end
if printerState == 'buffering' or printerState == 'printing' or printerState == 'stopping' then
response:setFail("Printer is busy, please wait")
return false
end
return true
end
function M._global_GET(request, response) function M._global_GET(request, response)
response:setSuccess() response:setSuccess()
for k,v in pairs(request:getAll()) do for k,v in pairs(request:getAll()) do
local r,m = settings.get(k) local r,m = settings.get(k)
if r ~= nil then response:addData(k, r) if r ~= nil then response:addData(k, r)
else response:addData(k, "could not read key ('" .. m .. "')") else response:addData(k, "could not read key ('" .. m .. "')")
end end
@ -22,27 +48,30 @@ end
function M._global_POST(request, response) function M._global_POST(request, response)
--log:info("API:config:set") --log:info("API:config:set")
if not operationsAccessOrFail(request, response) then return end
response:setSuccess() response:setSuccess()
local validation = {} local validation = {}
for k,v in pairs(request:getAll()) do for k,v in pairs(request:getAll()) do
--log:info(" "..k..": "..v); --log:info(" "..k..": "..v);
local r,m = settings.set(k, v) local r,m = settings.set(k, v)
if r then if r then
--response:addData(k, "ok") --response:addData(k, "ok")
validation[k] = "ok" validation[k] = "ok"
else else
--response:addData(k, "could not save setting ('" .. m .. "')") --response:addData(k, "could not save setting ('" .. m .. "')")
validation[k] = "could not save setting ('" .. m .. "')" validation[k] = "could not save setting ('" .. m .. "')"
log:info(" m: "..utils.dump(m)) log:info(" m: "..utils.dump(m))
end end
end end
response:addData("validation",validation) response:addData("validation",validation)
local substitutedSsid = wifi.getSubstitutedSsid(settings.get('network.ap.ssid')) local substitutedSsid = wifi.getSubstitutedSsid(settings.get('network.ap.ssid'))
response:addData("substituted_ssid",substitutedSsid) response:addData("substituted_ssid",substitutedSsid)
log:info("API:Network:try signing in") log:info("API:Network:try signing in")
if signin.signin() then if signin.signin() then
log:info("API:Network:signin successfull") log:info("API:Network:signin successfull")

View File

@ -5,12 +5,36 @@ local netconf = require('network.netconfig')
local wifi = require('network.wlanconfig') local wifi = require('network.wlanconfig')
local ResponseClass = require('rest.response') local ResponseClass = require('rest.response')
local signin = require('network.signin') local signin = require('network.signin')
local accessManager = require('util.access')
local printerAPI = require('rest.api.api_printer')
local M = { local M = {
isApi = true isApi = true
} }
-- TODO: this function is also defined in 2 other places, combine them (and avoid require loops)
local function operationsAccessOrFail(request, response)
if not accessManager.hasControl(request.remoteAddress) then
response:setFail("No control access")
return false
end
local rv, printerState = printerAPI.state(request, response, true)
if(rv == false) then
response:setError("Could not get printer state")
return false
end
if printerState == 'buffering' or printerState == 'printing' or printerState == 'stopping' then
response:setFail("Printer is busy, please wait")
return false
end
return true
end
function M._global(request, response) function M._global(request, response)
response:setError("not implemented") response:setError("not implemented")
end end
@ -82,7 +106,7 @@ function M.status(request, response)
response:addData("status",statusCode) response:addData("status",statusCode)
response:addData("statusMessage",statusMessage) response:addData("statusMessage",statusMessage)
response:setSuccess(statusMessage) response:setSuccess(statusMessage)
response:addData("ssid", ds.ssid or "") response:addData("ssid", ds.ssid or "")
response:addData("bssid", ds.bssid or "") response:addData("bssid", ds.bssid or "")
response:addData("channel", ds.channel or "") response:addData("channel", ds.channel or "")
@ -93,11 +117,11 @@ function M.status(request, response)
response:addData("txpower", ds.txpower) response:addData("txpower", ds.txpower)
response:addData("signal", ds.signal) response:addData("signal", ds.signal)
response:addData("noise", ds.noise) response:addData("noise", ds.noise)
if withRaw then response:addData("_raw", utils.dump(ds)) end if withRaw then response:addData("_raw", utils.dump(ds)) end
local localip = wifi.getLocalIP() local localip = wifi.getLocalIP()
response:addData("localip", localip) response:addData("localip", localip)
end end
@ -112,27 +136,32 @@ function M.associate_POST(request, response)
response:setError("missing ssid argument") response:setError("missing ssid argument")
return return
end end
if not operationsAccessOrFail(request, response) then return end
response:setSuccess("wlan is trying to associate") response:setSuccess("wlan is trying to associate")
local rv,msg = netconf.associateSsid(argSsid, argPhrase, argRecreate) local rv,msg = netconf.associateSsid(argSsid, argPhrase, argRecreate)
if rv then if rv then
log:info("associated to wifi: "..utils.dump(argSsid)) log:info("associated to wifi: "..utils.dump(argSsid))
else else
log:info("failed to associate to wifi: "..utils.dump(argSsid).." ("..utils.dump(msg)..")") log:info("failed to associate to wifi: "..utils.dump(argSsid).." ("..utils.dump(msg)..")")
end end
end end
function M.disassociate_POST(request, response) function M.disassociate_POST(request, response)
if not operationsAccessOrFail(request, response) then return end
local rv = netconf.disassociate() local rv = netconf.disassociate()
response:setSuccess("all wireless networks deactivated") response:setSuccess("all wireless networks deactivated")
response:addData("wifi_restart_result", rv) response:addData("wifi_restart_result", rv)
end end
function M.openap_POST(request, response) function M.openap_POST(request, response)
if not operationsAccessOrFail(request, response) then return end
local ssid = wifi.getSubstitutedSsid(settings.get('network.ap.ssid')) local ssid = wifi.getSubstitutedSsid(settings.get('network.ap.ssid'))
local rv,msg = netconf.setupAccessPoint(ssid) local rv,msg = netconf.setupAccessPoint(ssid)
@ -154,6 +183,8 @@ function M.remove_POST(request, response)
return return
end end
if not operationsAccessOrFail(request, response) then return end
if wifi.removeConfig(argSsid) then if wifi.removeConfig(argSsid) then
response:setSuccess("removed wireless network with requested SSID") response:setSuccess("removed wireless network with requested SSID")
response:addData("ssid", argSsid) response:addData("ssid", argSsid)
@ -170,7 +201,7 @@ function M.signin(request, response)
log:info("API:Network:signed in") log:info("API:Network:signed in")
response:setSuccess("API:Network:signed in") response:setSuccess("API:Network:signed in")
response:addData("response", output) response:addData("response", output)
else else
log:info("API:Network:Signing in failed") log:info("API:Network:Signing in failed")
response:setError("Signing in failed") response:setError("Signing in failed")
end end

View File

@ -34,7 +34,7 @@ function M.temperature(request, response)
response:setError(msg) response:setError(msg)
return false; return false;
end end
return true; return true;
end end
@ -56,32 +56,37 @@ function M.progress(request, response)
response:setError(bufferedLines) response:setError(bufferedLines)
return false return false
end end
return true; return true;
end end
function M.state(request, response) -- NOTE: onlyReturnState is optional and prevents response from being modified
function M.state(request, response, onlyReturnState)
local argId = request:get("id") local argId = request:get("id")
response:addData('id', argId) if not onlyReturnState then response:addData('id', argId) end
local printer,msg = printerUtils.createPrinterOrFail(argId, response) local printer,msg = printerUtils.createPrinterOrFail(argId, response)
if not printer then if not printer then
response:setSuccess()
local printerState = "disconnected" local printerState = "disconnected"
response:addData('state', printerState) if not onlyReturnState then
response:setSuccess()
response:addData('state', printerState)
end
return true, printerState return true, printerState
else else
local rv,msg = printer:getState() local rv,msg = printer:getState()
if rv then if rv then
response:setSuccess() if not onlyReturnState then
response:addData('state', rv) response:setSuccess()
response:addData('state', rv)
end
return true, rv return true, rv
else else
response:setError(msg) if not onlyReturnState then response:setError(msg) end
return false return false
end end
end end
return true; return true
end end
function M.heatup_POST(request, response) function M.heatup_POST(request, response)
@ -116,14 +121,14 @@ function M.stop_POST(request, response)
local argId = request:get("id") local argId = request:get("id")
local printer,msg = printerUtils.createPrinterOrFail(argId, response) local printer,msg = printerUtils.createPrinterOrFail(argId, response)
if not printer then return end if not printer then return end
-- replacing {printingTemp} and {preheatTemp} in endgcode -- replacing {printingTemp} and {preheatTemp} in endgcode
local printingTemperature = settings.get('printer.temperature') local printingTemperature = settings.get('printer.temperature')
local printingBedTemperature = settings.get('printer.bed.temperature') local printingBedTemperature = settings.get('printer.bed.temperature')
local preheatTemperature = settings.get('printer.heatup.temperature') local preheatTemperature = settings.get('printer.heatup.temperature')
local preheatBedTemperature = settings.get('printer.heatup.bed.temperature') local preheatBedTemperature = settings.get('printer.heatup.bed.temperature')
local endGcode = settings.get('printer.endgcode') local endGcode = settings.get('printer.endgcode')
--log:info(" printingBedTemperature: "..utils.dump(printingBedTemperature)) --log:info(" printingBedTemperature: "..utils.dump(printingBedTemperature))
--log:info(" preheatBedTemperature: "..utils.dump(preheatBedTemperature)) --log:info(" preheatBedTemperature: "..utils.dump(preheatBedTemperature))
--log:info(" endGcode : "..utils.dump(endGcode)) --log:info(" endGcode : "..utils.dump(endGcode))
@ -132,7 +137,7 @@ function M.stop_POST(request, response)
endGcode = string.gsub(endGcode,"{preheatTemp}",preheatTemperature) endGcode = string.gsub(endGcode,"{preheatTemp}",preheatTemperature)
endGcode = string.gsub(endGcode,"{preheatBedTemp}",preheatBedTemperature) endGcode = string.gsub(endGcode,"{preheatBedTemp}",preheatBedTemperature)
--log:info(" >endGcode : "..utils.dump(endGcode)) --log:info(" >endGcode : "..utils.dump(endGcode))
local rv,msg = printer:stopPrint(endGcode) local rv,msg = printer:stopPrint(endGcode)
response:addData('id', argId) response:addData('id', argId)

View File

@ -6,33 +6,58 @@ arg = argStash
local log = require('util.logger') local log = require('util.logger')
local utils = require('util.utils') local utils = require('util.utils')
local accessManager = require('util.access')
local printerAPI = require('rest.api.api_printer')
local M = { local M = {
isApi = true isApi = true
} }
-- TODO: this function is also defined in 2 other places, combine them (and avoid require loops)
local function operationsAccessOrFail(request, response)
if not accessManager.hasControl(request.remoteAddress) then
response:setFail("No control access")
return false
end
local rv, printerState = printerAPI.state(request, response, true)
if(rv == false) then
response:setError("Could not get printer state")
return false
end
if printerState == 'buffering' or printerState == 'printing' or printerState == 'stopping' then
response:setFail("Printer is busy, please wait")
return false
end
return true
end
function M.status(request, response) function M.status(request, response)
updater.setLogger(log) updater.setLogger(log)
updater.setUseCache(false) updater.setUseCache(false)
local success,status,msg = updater.getStatus() local success,status,msg = updater.getStatus()
--response:addData('current_version', status.currentVersion) --response:addData('current_version', status.currentVersion)
response:addData('current_version', updater.formatVersion(status.currentVersion)) response:addData('current_version', updater.formatVersion(status.currentVersion))
response:addData('state_code', status.stateCode) response:addData('state_code', status.stateCode)
response:addData('state_text', status.stateText) response:addData('state_text', status.stateText)
if not success then if not success then
response:setFail(msg) response:setFail(msg)
return return
end end
local canUpdate = updater.compareVersions(status.newestVersion, status.currentVersion) > 0 local canUpdate = updater.compareVersions(status.newestVersion, status.currentVersion) > 0
--response:addData('newest_version', status.newestVersion) --response:addData('newest_version', status.newestVersion)
response:addData('newest_version', updater.formatVersion(status.newestVersion)) response:addData('newest_version', updater.formatVersion(status.newestVersion))
response:addData('can_update', canUpdate) response:addData('can_update', canUpdate)
if status.progress then response:addData('progress', status.progress) end if status.progress then response:addData('progress', status.progress) end
if status.imageSize then response:addData('image_size', status.imageSize) end if status.imageSize then response:addData('image_size', status.imageSize) end
response:setSuccess() response:setSuccess()
@ -49,23 +74,26 @@ function M.download_POST(request, response)
if argClearGcode == nil then argClearGcode = true end if argClearGcode == nil then argClearGcode = true end
if argClearImages == nil then argClearImages = true end if argClearImages == nil then argClearImages = true end
-- block access to prevent potential issues with printing (e.g. out of memory)
if not operationsAccessOrFail(request, response) then return end
updater.setLogger(log) updater.setLogger(log)
updater.setState(updater.STATE.DOWNLOADING,"") updater.setState(updater.STATE.DOWNLOADING,"")
local vEnt, rv, msg local vEnt, rv, msg
if not argVersion then if not argVersion then
local success,status,msg = updater.getStatus() local success,status,msg = updater.getStatus()
if not success then if not success then
updater.setState(updater.STATE.DOWNLOAD_FAILED, msg) updater.setState(updater.STATE.DOWNLOAD_FAILED, msg)
response:setFail(msg) response:setFail(msg)
return return
else else
argVersion = updater.formatVersion(status.newestVersion) argVersion = updater.formatVersion(status.newestVersion)
end end
end end
if argClearImages then if argClearImages then
rv,msg = updater.clear() rv,msg = updater.clear()
if not rv then if not rv then
@ -110,18 +138,20 @@ end
-- if successful, this call won't return since the device will flash its memory and reboot -- if successful, this call won't return since the device will flash its memory and reboot
function M.install_POST(request, response) function M.install_POST(request, response)
local argVersion = request:get("version") local argVersion = request:get("version")
updater.setLogger(log)
log:info("API:update/install") log:info("API:update/install")
if not operationsAccessOrFail(request, response) then return end
updater.setLogger(log)
updater.setState(updater.STATE.INSTALLING,"") updater.setState(updater.STATE.INSTALLING,"")
if not argVersion then if not argVersion then
local success,status,msg = updater.getStatus() local success,status,msg = updater.getStatus()
if not success then if not success then
updater.setState(updater.STATE.INSTALL_FAILED, msg) updater.setState(updater.STATE.INSTALL_FAILED, msg)
response:setFail(msg) response:setFail(msg)
return return
else else
argVersion = updater.formatVersion(status.newestVersion) argVersion = updater.formatVersion(status.newestVersion)
end end
end end
@ -142,7 +172,7 @@ function M.install_POST(request, response)
if not rv then if not rv then
updater.setState(updater.STATE.INSTALL_FAILED, "installation failed (" .. msg .. ")") updater.setState(updater.STATE.INSTALL_FAILED, "installation failed (" .. msg .. ")")
response:setFail("installation failed (" .. msg .. ")") response:setFail("installation failed (" .. msg .. ")")
else else
response:setSuccess() response:setSuccess()
end end
end end

View File

@ -16,6 +16,8 @@ function M.getController()
else else
controllerIP = file:read('*a') controllerIP = file:read('*a')
file:close() file:close()
--strip trailing newline (useful when manually editing controller.txt)
if controllerIP:find('\n') == controllerIP:len() then controllerIP = controllerIP:sub(0, -2) end
return controllerIP return controllerIP
end end
end end
@ -27,4 +29,4 @@ function M.setController(ip)
file:close() file:close()
end end
return M return M