From 2461d060e092d68b17e6e02f199ebc0d5dd48ca7 Mon Sep 17 00:00:00 2001 From: xAnavrins Date: Mon, 18 Jul 2022 00:07:55 -0400 Subject: [PATCH] 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 --- .gitignore | 1 + swshop/apis/k.lua | 17 ++++++--- swshop/apis/w.lua | 32 ++++++++++------ swshop/shopConfig.lua | 88 ++++++++++++++++++++++++++++++++----------- swshop/swshop.lua | 10 +++-- 5 files changed, 105 insertions(+), 43 deletions(-) diff --git a/.gitignore b/.gitignore index a5e9d77..b4752c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /etc/fstab /etc/recipes2.db +/.vscode diff --git a/swshop/apis/k.lua b/swshop/apis/k.lua index 4adf49e..d6e3208 100644 --- a/swshop/apis/k.lua +++ b/swshop/apis/k.lua @@ -4,9 +4,9 @@ local jua local json local await -local endpoint = "krist.ceriat.net" -local wsEndpoint = "ws://"..endpoint -local httpEndpoint = "http://"..endpoint +local endpoint = "krist.dev" +local wsEndpoint = "wss://"..endpoint +local httpEndpoint = "https://"..endpoint local function asserttype(var, name, vartype, optional) 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 +function setNodeUrl(url) + endpoint = url + wsEndpoint = "wss://"..endpoint + httpEndpoint = "https://"..endpoint +end + function init(juai, jsoni, wi, ri) asserttype(juai, "jua", "table") asserttype(jsoni, "json", "table") @@ -53,7 +59,7 @@ local function authorize_websocket(cb, privatekey) asserttype(privatekey, "privatekey", "string", true) 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", { privatekey = privatekey }) @@ -175,7 +181,7 @@ local wsEventNameLookup = { ownNames = "name", ownWebhooks = "webhook", motd = "motd", - keepalive = "keepalive", + keepalive = "keepalive" } local wsEvents = {} @@ -367,6 +373,7 @@ function parseMeta(meta) end return { + setNodeUrl = setNodeUrl, init = init, address = address, addressTransactions = addressTransactions, diff --git a/swshop/apis/w.lua b/swshop/apis/w.lua index 7fe1e3e..c0da9a4 100644 --- a/swshop/apis/w.lua +++ b/swshop/apis/w.lua @@ -79,10 +79,12 @@ function init(jua) jua.on("websocket_failure", function(event, url) local id = findID(url) - if id and callbackRegistry[id].failure then - callbackRegistry[id].failure(id) + if id then + if callbackRegistry[id].failure then + callbackRegistry[id].failure(id) + end + table.remove(callbackRegistry, id) end - table.remove(callbackRegistry, id) end) jua.on("websocket_message", function(event, url, data) @@ -94,10 +96,12 @@ function init(jua) jua.on("websocket_closed", function(event, url) local id = findID(url) - if id and callbackRegistry[id].closed then - callbackRegistry[id].closed(id) + if id then + if callbackRegistry[id].closed then + callbackRegistry[id].closed(id) + end + table.remove(callbackRegistry, id) end - table.remove(callbackRegistry, id) end) else jua.on("socket_connect", function(event, id) @@ -107,10 +111,12 @@ function init(jua) end) jua.on("socket_error", function(event, id, msg) - if id and callbackRegistry[id].failure then - callbackRegistry[id].failure(id, msg) + if id then + if callbackRegistry[id].failure then + callbackRegistry[id].failure(id, msg) + end + table.remove(callbackRegistry, id) end - table.remove(callbackRegistry, id) end) jua.on("socket_message", function(event, id) @@ -121,10 +127,12 @@ function init(jua) end) jua.on("socket_closed", function(event, id) - if id and callbackRegistry[id].closed then - callbackRegistry[id].closed(id) + if id then + if callbackRegistry[id].closed then + callbackRegistry[id].closed(id) + end + table.remove(callbackRegistry, id) end - table.remove(callbackRegistry, id) end) end end diff --git a/swshop/shopConfig.lua b/swshop/shopConfig.lua index 8c1ffba..fd7dd35 100644 --- a/swshop/shopConfig.lua +++ b/swshop/shopConfig.lua @@ -5,6 +5,8 @@ local colors = _G.colors local device = _G.device local os = _G.os +local defaultKristNode = "https://krist.dev" + --[[ Configuration Page ]]-- local wizardPage = UI.WizardPage { title = 'Store Front', @@ -13,28 +15,21 @@ local wizardPage = UI.WizardPage { x = 2, ex = -2, y = 1, ey = -2, manualControls = true, [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', help = 'Text to show in header', limit = 64, shadowText = "xxxx's shop", required = false, }, - [3] = UI.Checkbox { + [2] = UI.Checkbox { formLabel = 'Single shop', formKey = 'refundInvalid', help = 'Only this shop uses this domain', }, - [4] = UI.Checkbox { + [3] = UI.Checkbox { formLabel = 'Show out of stock', formKey = 'showOutOfStock', help = 'Show out of stock items in red', }, - [5] = UI.Chooser { + [4] = UI.Chooser { formLabel = 'RS Signal', formKey = 'rsSide', formIndex = 6, width = 10, choices = { @@ -47,7 +42,7 @@ local wizardPage = UI.WizardPage { }, required = true, }, - [6] = UI.Chooser { + [5] = UI.Chooser { width = 9, formIndex = 7, formLabel = 'Font Size', formKey = 'textScale', @@ -88,14 +83,33 @@ function wizardPage:isValidFor(node) end -- [[Password View]] -- -local passwordPage = UI.WizardPage { +local kristPage = UI.WizardPage { title = 'Krist Settings', index = 3, form = UI.Form { x = 2, ex = -2, y = 1, ey = -2, manualControls = true, - passEntry = UI.TextEntry { + + nodeEntry = UI.TextEntry { 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', shadowText = 'Password', help = 'Krist wallet password', @@ -103,15 +117,17 @@ local passwordPage = UI.WizardPage { required = true, pass = true, }, + pkeyCheck = UI.Checkbox { - formIndex = 2, - formLabel = 'Is private key', formKey = 'isPrivateKey', + formIndex = 5, + formLabel = 'Private key', formKey = 'isPrivateKey', help = 'Password is in private key format', ispkey = true, }, + preview = UI.TextEntry { - formIndex = 4, - formLabel = 'Using address', formKey = 'address', + formIndex = 7, + formLabel = 'Address', formKey = 'address', backgroundColor = 'primary', textColor = colors.yellow, inactive = true, @@ -127,7 +143,7 @@ local function makeAddress(text, isPrivateKey) return Krist.makev2address(privKey) end -function passwordPage.form:eventHandler(event) +function kristPage.form:eventHandler(event) if (event.type == 'text_change' and event.element.pass) or (event.type == 'checkbox_change' and event.element.ispkey) then 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) end -function passwordPage:setNode(node) +function kristPage:setNode(node) node.address = node.password and makeAddress(node.password, node.isPrivateKey) or '' + node.syncNode = node.syncNode or defaultKristNode self.form:setValues(node) end -function passwordPage:validate() - return self.form:save() +local function addressHasName(node, address, domain) + 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 -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' end -UI:getPage('nodeWizard').wizard:add({ storeFronta = wizardPage, storeFrontb = passwordPage }) +UI:getPage('nodeWizard').wizard:add({ storeFronta = wizardPage, storeFrontb = kristPage }) diff --git a/swshop/swshop.lua b/swshop/swshop.lua index 5634e11..8529f5a 100644 --- a/swshop/swshop.lua +++ b/swshop/swshop.lua @@ -21,16 +21,20 @@ local storage = Config.load('storage') Util.each(rs.getSides(), function(side) rs.setOutput(side, false) end) -r.init(jua) -w.init(jua) -k.init(jua, json, w, r) +local defaultKristNode = "https://krist.dev" local node = ({ ... })[1] or error('Node name is required') local config = storage[node] local privatekey = config.isPrivateKey and config.password or Krist.toKristWalletFormat(config.password) +local nodeurl = config.syncNode or defaultKristNode local address = Krist.makev2address(privatekey) 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() rs.setOutput(rsSide, false) jua.stop()