Updates to swshop part 1
Updated URL to new krist node Form now validates if address own provided domain Support for third-party sync nodes Update k.lua and w.lua Closes #60
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
/etc/fstab
|
/etc/fstab
|
||||||
/etc/recipes2.db
|
/etc/recipes2.db
|
||||||
|
/.vscode
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ local jua
|
|||||||
local json
|
local json
|
||||||
local await
|
local await
|
||||||
|
|
||||||
local endpoint = "krist.ceriat.net"
|
local endpoint = "krist.dev"
|
||||||
local wsEndpoint = "ws://"..endpoint
|
local wsEndpoint = "wss://"..endpoint
|
||||||
local httpEndpoint = "http://"..endpoint
|
local httpEndpoint = "https://"..endpoint
|
||||||
|
|
||||||
local function asserttype(var, name, vartype, optional)
|
local function asserttype(var, name, vartype, optional)
|
||||||
if not (type(var) == vartype or optional and type(var) == "nil") then
|
if not (type(var) == vartype or optional and type(var) == "nil") then
|
||||||
@@ -14,6 +14,12 @@ local function asserttype(var, name, vartype, optional)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function setNodeUrl(url)
|
||||||
|
endpoint = url
|
||||||
|
wsEndpoint = "wss://"..endpoint
|
||||||
|
httpEndpoint = "https://"..endpoint
|
||||||
|
end
|
||||||
|
|
||||||
function init(juai, jsoni, wi, ri)
|
function init(juai, jsoni, wi, ri)
|
||||||
asserttype(juai, "jua", "table")
|
asserttype(juai, "jua", "table")
|
||||||
asserttype(jsoni, "json", "table")
|
asserttype(jsoni, "json", "table")
|
||||||
@@ -53,7 +59,7 @@ local function authorize_websocket(cb, privatekey)
|
|||||||
asserttype(privatekey, "privatekey", "string", true)
|
asserttype(privatekey, "privatekey", "string", true)
|
||||||
|
|
||||||
api_request(function(success, data)
|
api_request(function(success, data)
|
||||||
cb(success and data and data.ok, data.url and data.url:gsub("wss:", "ws:") or data)
|
cb(success and data and data.ok, data.url and data.url:gsub("ws:", "wss:") or data)
|
||||||
end, "/ws/start", {
|
end, "/ws/start", {
|
||||||
privatekey = privatekey
|
privatekey = privatekey
|
||||||
})
|
})
|
||||||
@@ -175,7 +181,7 @@ local wsEventNameLookup = {
|
|||||||
ownNames = "name",
|
ownNames = "name",
|
||||||
ownWebhooks = "webhook",
|
ownWebhooks = "webhook",
|
||||||
motd = "motd",
|
motd = "motd",
|
||||||
keepalive = "keepalive",
|
keepalive = "keepalive"
|
||||||
}
|
}
|
||||||
|
|
||||||
local wsEvents = {}
|
local wsEvents = {}
|
||||||
@@ -367,6 +373,7 @@ function parseMeta(meta)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
setNodeUrl = setNodeUrl,
|
||||||
init = init,
|
init = init,
|
||||||
address = address,
|
address = address,
|
||||||
addressTransactions = addressTransactions,
|
addressTransactions = addressTransactions,
|
||||||
|
|||||||
@@ -79,10 +79,12 @@ function init(jua)
|
|||||||
|
|
||||||
jua.on("websocket_failure", function(event, url)
|
jua.on("websocket_failure", function(event, url)
|
||||||
local id = findID(url)
|
local id = findID(url)
|
||||||
if id and callbackRegistry[id].failure then
|
if id then
|
||||||
|
if callbackRegistry[id].failure then
|
||||||
callbackRegistry[id].failure(id)
|
callbackRegistry[id].failure(id)
|
||||||
end
|
end
|
||||||
table.remove(callbackRegistry, id)
|
table.remove(callbackRegistry, id)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
jua.on("websocket_message", function(event, url, data)
|
jua.on("websocket_message", function(event, url, data)
|
||||||
@@ -94,10 +96,12 @@ function init(jua)
|
|||||||
|
|
||||||
jua.on("websocket_closed", function(event, url)
|
jua.on("websocket_closed", function(event, url)
|
||||||
local id = findID(url)
|
local id = findID(url)
|
||||||
if id and callbackRegistry[id].closed then
|
if id then
|
||||||
|
if callbackRegistry[id].closed then
|
||||||
callbackRegistry[id].closed(id)
|
callbackRegistry[id].closed(id)
|
||||||
end
|
end
|
||||||
table.remove(callbackRegistry, id)
|
table.remove(callbackRegistry, id)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
jua.on("socket_connect", function(event, id)
|
jua.on("socket_connect", function(event, id)
|
||||||
@@ -107,10 +111,12 @@ function init(jua)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
jua.on("socket_error", function(event, id, msg)
|
jua.on("socket_error", function(event, id, msg)
|
||||||
if id and callbackRegistry[id].failure then
|
if id then
|
||||||
|
if callbackRegistry[id].failure then
|
||||||
callbackRegistry[id].failure(id, msg)
|
callbackRegistry[id].failure(id, msg)
|
||||||
end
|
end
|
||||||
table.remove(callbackRegistry, id)
|
table.remove(callbackRegistry, id)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
jua.on("socket_message", function(event, id)
|
jua.on("socket_message", function(event, id)
|
||||||
@@ -121,10 +127,12 @@ function init(jua)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
jua.on("socket_closed", function(event, id)
|
jua.on("socket_closed", function(event, id)
|
||||||
if id and callbackRegistry[id].closed then
|
if id then
|
||||||
|
if callbackRegistry[id].closed then
|
||||||
callbackRegistry[id].closed(id)
|
callbackRegistry[id].closed(id)
|
||||||
end
|
end
|
||||||
table.remove(callbackRegistry, id)
|
table.remove(callbackRegistry, id)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ local colors = _G.colors
|
|||||||
local device = _G.device
|
local device = _G.device
|
||||||
local os = _G.os
|
local os = _G.os
|
||||||
|
|
||||||
|
local defaultKristNode = "https://krist.dev"
|
||||||
|
|
||||||
--[[ Configuration Page ]]--
|
--[[ Configuration Page ]]--
|
||||||
local wizardPage = UI.WizardPage {
|
local wizardPage = UI.WizardPage {
|
||||||
title = 'Store Front',
|
title = 'Store Front',
|
||||||
@@ -13,28 +15,21 @@ local wizardPage = UI.WizardPage {
|
|||||||
x = 2, ex = -2, y = 1, ey = -2,
|
x = 2, ex = -2, y = 1, ey = -2,
|
||||||
manualControls = true,
|
manualControls = true,
|
||||||
[1] = UI.TextEntry {
|
[1] = UI.TextEntry {
|
||||||
formLabel = 'Domain', formKey = 'domain',
|
|
||||||
help = 'Krist wallet domain (minus .kst)',
|
|
||||||
limit = 64,
|
|
||||||
shadowText = 'example',
|
|
||||||
required = true,
|
|
||||||
},
|
|
||||||
[2] = UI.TextEntry {
|
|
||||||
formLabel = 'Header', formKey = 'header',
|
formLabel = 'Header', formKey = 'header',
|
||||||
help = 'Text to show in header',
|
help = 'Text to show in header',
|
||||||
limit = 64,
|
limit = 64,
|
||||||
shadowText = "xxxx's shop",
|
shadowText = "xxxx's shop",
|
||||||
required = false,
|
required = false,
|
||||||
},
|
},
|
||||||
[3] = UI.Checkbox {
|
[2] = UI.Checkbox {
|
||||||
formLabel = 'Single shop', formKey = 'refundInvalid',
|
formLabel = 'Single shop', formKey = 'refundInvalid',
|
||||||
help = 'Only this shop uses this domain',
|
help = 'Only this shop uses this domain',
|
||||||
},
|
},
|
||||||
[4] = UI.Checkbox {
|
[3] = UI.Checkbox {
|
||||||
formLabel = 'Show out of stock', formKey = 'showOutOfStock',
|
formLabel = 'Show out of stock', formKey = 'showOutOfStock',
|
||||||
help = 'Show out of stock items in red',
|
help = 'Show out of stock items in red',
|
||||||
},
|
},
|
||||||
[5] = UI.Chooser {
|
[4] = UI.Chooser {
|
||||||
formLabel = 'RS Signal', formKey = 'rsSide', formIndex = 6,
|
formLabel = 'RS Signal', formKey = 'rsSide', formIndex = 6,
|
||||||
width = 10,
|
width = 10,
|
||||||
choices = {
|
choices = {
|
||||||
@@ -47,7 +42,7 @@ local wizardPage = UI.WizardPage {
|
|||||||
},
|
},
|
||||||
required = true,
|
required = true,
|
||||||
},
|
},
|
||||||
[6] = UI.Chooser {
|
[5] = UI.Chooser {
|
||||||
width = 9,
|
width = 9,
|
||||||
formIndex = 7,
|
formIndex = 7,
|
||||||
formLabel = 'Font Size', formKey = 'textScale',
|
formLabel = 'Font Size', formKey = 'textScale',
|
||||||
@@ -88,14 +83,33 @@ function wizardPage:isValidFor(node)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- [[Password View]] --
|
-- [[Password View]] --
|
||||||
local passwordPage = UI.WizardPage {
|
local kristPage = UI.WizardPage {
|
||||||
title = 'Krist Settings',
|
title = 'Krist Settings',
|
||||||
index = 3,
|
index = 3,
|
||||||
form = UI.Form {
|
form = UI.Form {
|
||||||
x = 2, ex = -2, y = 1, ey = -2,
|
x = 2, ex = -2, y = 1, ey = -2,
|
||||||
manualControls = true,
|
manualControls = true,
|
||||||
passEntry = UI.TextEntry {
|
|
||||||
|
nodeEntry = UI.TextEntry {
|
||||||
formIndex = 1,
|
formIndex = 1,
|
||||||
|
formLabel = 'Sync Node', formKey = 'syncNode',
|
||||||
|
shadowText = 'http(s)://domain:port',
|
||||||
|
help = 'Sync node the shop will use',
|
||||||
|
limit = 256,
|
||||||
|
required = true,
|
||||||
|
},
|
||||||
|
|
||||||
|
domainEntry = UI.TextEntry {
|
||||||
|
formIndex = 3,
|
||||||
|
formLabel = 'Domain', formKey = 'domain',
|
||||||
|
help = 'Krist wallet domain (minus .kst)',
|
||||||
|
limit = 64,
|
||||||
|
shadowText = 'example',
|
||||||
|
required = true,
|
||||||
|
},
|
||||||
|
|
||||||
|
passEntry = UI.TextEntry {
|
||||||
|
formIndex = 4,
|
||||||
formLabel = 'Password', formKey = 'password',
|
formLabel = 'Password', formKey = 'password',
|
||||||
shadowText = 'Password',
|
shadowText = 'Password',
|
||||||
help = 'Krist wallet password',
|
help = 'Krist wallet password',
|
||||||
@@ -103,15 +117,17 @@ local passwordPage = UI.WizardPage {
|
|||||||
required = true,
|
required = true,
|
||||||
pass = true,
|
pass = true,
|
||||||
},
|
},
|
||||||
|
|
||||||
pkeyCheck = UI.Checkbox {
|
pkeyCheck = UI.Checkbox {
|
||||||
formIndex = 2,
|
formIndex = 5,
|
||||||
formLabel = 'Is private key', formKey = 'isPrivateKey',
|
formLabel = 'Private key', formKey = 'isPrivateKey',
|
||||||
help = 'Password is in private key format',
|
help = 'Password is in private key format',
|
||||||
ispkey = true,
|
ispkey = true,
|
||||||
},
|
},
|
||||||
|
|
||||||
preview = UI.TextEntry {
|
preview = UI.TextEntry {
|
||||||
formIndex = 4,
|
formIndex = 7,
|
||||||
formLabel = 'Using address', formKey = 'address',
|
formLabel = 'Address', formKey = 'address',
|
||||||
backgroundColor = 'primary',
|
backgroundColor = 'primary',
|
||||||
textColor = colors.yellow,
|
textColor = colors.yellow,
|
||||||
inactive = true,
|
inactive = true,
|
||||||
@@ -127,7 +143,7 @@ local function makeAddress(text, isPrivateKey)
|
|||||||
return Krist.makev2address(privKey)
|
return Krist.makev2address(privKey)
|
||||||
end
|
end
|
||||||
|
|
||||||
function passwordPage.form:eventHandler(event)
|
function kristPage.form:eventHandler(event)
|
||||||
if (event.type == 'text_change' and event.element.pass) or
|
if (event.type == 'text_change' and event.element.pass) or
|
||||||
(event.type == 'checkbox_change' and event.element.ispkey) then
|
(event.type == 'checkbox_change' and event.element.ispkey) then
|
||||||
self.passEntry.shadowText = self.pkeyCheck.value and 'Private key' or 'Password'
|
self.passEntry.shadowText = self.pkeyCheck.value and 'Private key' or 'Password'
|
||||||
@@ -137,17 +153,43 @@ function passwordPage.form:eventHandler(event)
|
|||||||
return UI.Form.eventHandler(self, event)
|
return UI.Form.eventHandler(self, event)
|
||||||
end
|
end
|
||||||
|
|
||||||
function passwordPage:setNode(node)
|
function kristPage:setNode(node)
|
||||||
node.address = node.password and makeAddress(node.password, node.isPrivateKey) or ''
|
node.address = node.password and makeAddress(node.password, node.isPrivateKey) or ''
|
||||||
|
node.syncNode = node.syncNode or defaultKristNode
|
||||||
self.form:setValues(node)
|
self.form:setValues(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
function passwordPage:validate()
|
local function addressHasName(node, address, domain)
|
||||||
return self.form:save()
|
local res, err = http.get(node .. "/addresses/" .. address .. "/names")
|
||||||
|
if res then
|
||||||
|
local data = textutils.unserializeJSON(res.readAll())
|
||||||
|
if data.ok then
|
||||||
|
for _, name in pairs(data.names) do
|
||||||
|
if name.name == domain then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false, "This address doesn't own this name"
|
||||||
|
end
|
||||||
|
return false, data.error
|
||||||
|
end
|
||||||
|
return false, "Error while checking names"
|
||||||
end
|
end
|
||||||
|
|
||||||
function passwordPage:isValidFor(node)
|
function kristPage:validate()
|
||||||
|
local ok, err = http.checkURL(self.form.nodeEntry.value or '')
|
||||||
|
|
||||||
|
if ok then
|
||||||
|
ok, err = addressHasName(self.form.nodeEntry.value, self.form.preview.value, self.form.domainEntry.value)
|
||||||
|
if ok then
|
||||||
|
return self.form:save()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:emit({ type = 'general_error', message = err })
|
||||||
|
end
|
||||||
|
|
||||||
|
function kristPage:isValidFor(node)
|
||||||
return node.mtype == 'shop'
|
return node.mtype == 'shop'
|
||||||
end
|
end
|
||||||
|
|
||||||
UI:getPage('nodeWizard').wizard:add({ storeFronta = wizardPage, storeFrontb = passwordPage })
|
UI:getPage('nodeWizard').wizard:add({ storeFronta = wizardPage, storeFrontb = kristPage })
|
||||||
|
|||||||
@@ -21,16 +21,20 @@ local storage = Config.load('storage')
|
|||||||
|
|
||||||
Util.each(rs.getSides(), function(side) rs.setOutput(side, false) end)
|
Util.each(rs.getSides(), function(side) rs.setOutput(side, false) end)
|
||||||
|
|
||||||
r.init(jua)
|
local defaultKristNode = "https://krist.dev"
|
||||||
w.init(jua)
|
|
||||||
k.init(jua, json, w, r)
|
|
||||||
|
|
||||||
local node = ({ ... })[1] or error('Node name is required')
|
local node = ({ ... })[1] or error('Node name is required')
|
||||||
local config = storage[node]
|
local config = storage[node]
|
||||||
local privatekey = config.isPrivateKey and config.password or Krist.toKristWalletFormat(config.password)
|
local privatekey = config.isPrivateKey and config.password or Krist.toKristWalletFormat(config.password)
|
||||||
|
local nodeurl = config.syncNode or defaultKristNode
|
||||||
local address = Krist.makev2address(privatekey)
|
local address = Krist.makev2address(privatekey)
|
||||||
local rsSide = config.rsSide or 'top'
|
local rsSide = config.rsSide or 'top'
|
||||||
|
|
||||||
|
r.init(jua)
|
||||||
|
w.init(jua)
|
||||||
|
k.setNodeUrl(nodeurl:gsub("https?://", ""))
|
||||||
|
k.init(jua, json, w, r)
|
||||||
|
|
||||||
jua.on("terminate", function()
|
jua.on("terminate", function()
|
||||||
rs.setOutput(rsSide, false)
|
rs.setOutput(rsSide, false)
|
||||||
jua.stop()
|
jua.stop()
|
||||||
|
|||||||
Reference in New Issue
Block a user