From b730daf7fb5dad5e797d7eb63a0ac5154b0e37d0 Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 01/13] gluon-core: introduce "gluon" uci section --- package/gluon-core/files/etc/config/gluon | 1 + 1 file changed, 1 insertion(+) create mode 100644 package/gluon-core/files/etc/config/gluon diff --git a/package/gluon-core/files/etc/config/gluon b/package/gluon-core/files/etc/config/gluon new file mode 100644 index 00000000..e02fa678 --- /dev/null +++ b/package/gluon-core/files/etc/config/gluon @@ -0,0 +1 @@ +config system system From 0834985205e1a26d86dab8122693ef657798b06d Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 02/13] check_site_lib: merge site & domain and provide restricting feature - provide in_domain() and in_site() functions to restrict usage: need_string('foo.bar') -- allowed in both domain and site config need_string(in_site('foo.bar')) -- only allowed in site config need_string(in_domain('foo.bar')) -- only allowed in domain config - need_* merge the domain and site configs while prefering the domain values --- package/gluon-site/Makefile | 7 +- package/gluon.mk | 19 +++++- scripts/check_site_lib.lua | 128 +++++++++++++++++++++++++++--------- scripts/domain_config.lua | 13 ++++ 4 files changed, 133 insertions(+), 34 deletions(-) create mode 100644 scripts/domain_config.lua diff --git a/package/gluon-site/Makefile b/package/gluon-site/Makefile index 124dc49b..8118b5f8 100644 --- a/package/gluon-site/Makefile +++ b/package/gluon-site/Makefile @@ -8,7 +8,7 @@ PKG_VERSION:=$(if $(DUMP),x,$(GLUON_SITE_VERSION)) PKG_CONFIG_DEPENDS := CONFIG_GLUON_RELEASE CONFIG_GLUON_SITEDIR -PKG_FILE_DEPENDS := $(GLUON_SITEDIR)/site.conf $(GLUON_SITEDIR)/i18n/ +PKG_FILE_DEPENDS := $(GLUON_SITEDIR)/site.conf $(GLUON_SITEDIR)/domains/ $(GLUON_SITEDIR)/i18n/ PKG_BUILD_DEPENDS := lua-cjson/host PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) @@ -38,6 +38,7 @@ endef define Build/Prepare mkdir -p $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR)/domains endef define Build/Configure @@ -45,12 +46,16 @@ endef define Build/Compile GLUON_SITEDIR='$(call qstrip,$(CONFIG_GLUON_SITEDIR))' lua -e 'print(require("cjson").encode(assert(dofile("../../scripts/site_config.lua"))))' > $(PKG_BUILD_DIR)/site.json + ls $(call qstrip,$(CONFIG_GLUON_SITEDIR))/domains/*.conf > /dev/null # at least one domain cfg has to exist + for domain_cfg in `find $(call qstrip,$(CONFIG_GLUON_SITEDIR))/domains/ -iname \*.conf -printf "%f\n"`; do dc=$$$${domain_cfg%.conf}; GLUON_SITEDIR='$(call qstrip,$(CONFIG_GLUON_SITEDIR))' lua -e 'print(require("cjson").encode(assert(dofile("../../scripts/domain_config.lua")("'$$$${dc}'"))))' > $(PKG_BUILD_DIR)/domains/$$$${dc}.json; done $(call GluonBuildI18N,gluon-site,$(GLUON_SITEDIR)/i18n) endef define Package/gluon-site/install $(INSTALL_DIR) $(1)/lib/gluon $(INSTALL_DATA) $(PKG_BUILD_DIR)/site.json $(1)/lib/gluon/ + $(INSTALL_DIR) $(1)/lib/gluon/domains + $(CP) $(PKG_BUILD_DIR)/domains/*.json $(1)/lib/gluon/domains/ echo '$(GLUON_SITE_VERSION)' > $(1)/lib/gluon/site-version echo '$(call qstrip,$(CONFIG_GLUON_RELEASE))' > $(1)/lib/gluon/release diff --git a/package/gluon.mk b/package/gluon.mk index ab46dc22..e20d6bf9 100644 --- a/package/gluon.mk +++ b/package/gluon.mk @@ -11,7 +11,24 @@ local site_json = f:read('*a') f:close() site = require('cjson').decode(site_json) -$(shell cat '$(TOPDIR)/../scripts/check_site_lib.lua' '$(1)' | sed -ne '1h; 1!H; $$ {g; s/@/+@/g; s/\n/-@/g; p}') + +function check_domain(domain_code, domain) + $(shell cat '$(TOPDIR)/../scripts/check_site_lib.lua' '$(1)' | sed -ne '1h; 1!H; $$ {g; s/@/+@/g; s/\n/-@/g; p}') +end + +local dir = os.getenv('IPKG_INSTROOT') .. '/lib/gluon/domains/' +local pfile = io.popen('find '..dir..' -iname \\*.json') +for domain_path in pfile:lines() do + local domain_code = string.gmatch(domain_path, '([^/]+).json$$')() + local f = assert(io.open(domain_path)) + local domain_json = f:read('*a') + f:close() + + domain = require('cjson').decode(domain_json) + + check_domain(domain_code, domain) +end +pfile:close() END__GLUON__CHECK__SITE endef diff --git a/scripts/check_site_lib.lua b/scripts/check_site_lib.lua index 9e2bd135..a82e8352 100644 --- a/scripts/check_site_lib.lua +++ b/scripts/check_site_lib.lua @@ -1,9 +1,32 @@ local function loadvar(varname) - local ok, val = pcall(assert(loadstring('return site.' .. varname))) - if ok then - return val + local ok, val = pcall(assert(loadstring('return domain.' .. varname))) + if ok and val ~= nil then + return val, 'domains/'..domain_code..'.conf' + end + + ok, val = pcall(assert(loadstring('return site.' .. varname))) + if ok and val ~= nil then + return val, 'site.conf' else - return nil + return nil, 'site.conf or domains/'..domain_code..'.conf' + end +end + +local function loadvar_domain(varname) + local ok, val = pcall(assert(loadstring('return domain.' .. varname))) + if ok then + return val, 'domains/'..domain_code..'.conf' + else + return nil, 'domains/'..domain_code..'.conf' + end +end + +local function loadvar_site(varname) + ok, val = pcall(assert(loadstring('return site.' .. varname))) + if ok then + return val, 'site.conf' + else + return nil, 'site.conf' end end @@ -32,68 +55,87 @@ local function assert_type(var, t, msg) assert(type(var) == t, msg) end +-- returns an unique keys in keys of returned table +function keys_merged(a, b) + keys_table = {} + for k, _ in pairs(a or {}) do + keys_table[k] = 1 + end + for k, _ in pairs(b or {}) do + keys_table[k] = 1 + end + return keys_table +end -function assert_uci_name(var) +function forbid_in_domain(varname) + local ok, val = pcall(assert(loadstring('return domain.' .. varname))) + assert(not ok or val == nil, "domains/"..domain_code..".conf error: `"..varname.."` is not allowed in domain specific config.") +end + +function forbid_in_site(varname) + local ok, val = pcall(assert(loadstring('return site.' .. varname))) + assert(not ok or val == nil, "site.conf error: `"..varname.."` is not allowed in site config.") +end + +function assert_uci_name(var, conf_name) -- We don't use character classes like %w here to be independent of the locale - assert(var:match('^[0-9a-zA-Z_]+$'), "site.conf error: `" .. var .. "' is not a valid config section name (only alphanumeric characters and the underscore are allowed)") + assert(var:match('^[0-9a-zA-Z_]+$'), conf_name.." error: `" .. var .. "' is not a valid config section name (only alphanumeric characters and the underscore are allowed)") end function need_string(varname, required) - local var = loadvar(varname) + local var, conf_name = loadvar(varname) if required == false and var == nil then - return nil + return nil, conf_name end - assert_type(var, 'string', "site.conf error: expected `" .. varname .. "' to be a string") - return var + assert_type(var, 'string', conf_name .. " error: expected `" .. varname .. "' to be a string") + return var, conf_name end function need_string_match(varname, pat, required) - local var = need_string(varname, required) + local var, conf_name = need_string(varname, required) if not var then return nil end - assert(var:match(pat), "site.conf error: expected `" .. varname .. "' to match pattern `" .. pat .. "'") + assert(var:match(pat), conf_name.." error: expected `" .. varname .. "' to match pattern `" .. pat .. "'") return var end function need_number(varname, required) - local var = loadvar(varname) + local var, conf_name = loadvar(varname) if required == false and var == nil then return nil end - assert_type(var, 'number', "site.conf error: expected `" .. varname .. "' to be a number") + assert_type(var, 'number', conf_name.." error: expected `" .. varname .. "' to be a number") return var end function need_boolean(varname, required) - local var = loadvar(varname) + local var, conf_name = loadvar(varname) if required == false and var == nil then return nil end - assert_type(var, 'boolean', "site.conf error: expected `" .. varname .. "' to be a boolean") + assert_type(var, 'boolean', conf_name.." error: expected `" .. varname .. "' to be a boolean") return var end -function need_array(varname, subcheck, required) - local var = loadvar(varname) - +local function __need_array_from_var(var, varname, subcheck, required, conf_name) if required == false and var == nil then return nil end - assert_type(var, 'table', "site.conf error: expected `" .. varname .. "' to be an array") + assert_type(var, 'table', conf_name.." error: expected `" .. varname .. "' to be an array") for _, e in ipairs(var) do subcheck(e) @@ -102,18 +144,27 @@ function need_array(varname, subcheck, required) return var end +function need_array(varname, subcheck, required) + local var, conf_name = loadvar(varname) + return __need_array_from_var(var, varname, subcheck, required, conf_name) +end + + function need_table(varname, subcheck, required) - local var = loadvar(varname) + local var, conf_name = loadvar(varname) if required == false and var == nil then return nil end - assert_type(var, 'table', "site.conf error: expected `" .. varname .. "' to be a table") + assert_type(var, 'table', conf_name.." error: expected `" .. varname .. "' to be a table") + + local dvar = loadvar_domain(varname) + local svar = loadvar_site(varname) if subcheck then - for k, v in pairs(var) do - subcheck(k, v) + for k, _ in pairs(keys_merged(dvar, svar)) do + subcheck(k, conf_name) end end @@ -121,31 +172,44 @@ function need_table(varname, subcheck, required) end function need_one_of(varname, array, required) - local var = loadvar(varname) + local var, conf_name = loadvar(varname) if required == false and var == nil then return nil end - assert_one_of(var, array, "site.conf error: expected `" .. varname .. "' to be one of given array: " .. array_to_string(array)) + assert_one_of(var, array, conf_name.." error: expected `" .. varname .. "' to be one of given array: " .. array_to_string(array)) return var end function need_string_array(varname, required) - local ok, var = pcall(need_array, varname, function(e) assert_type(e, 'string') end, required) - assert(ok, "site.conf error: expected `" .. varname .. "' to be a string array") + local var, conf_name = loadvar(varname) + local ok, var = pcall(__need_array_from_var, var, varname, function(e) assert_type(e, 'string') end, required, conf_name) + assert(ok, conf_name.." error: expected `" .. varname .. "' to be a string array") return var end function need_string_array_match(varname, pat, required) - local ok, var = pcall(need_array, varname, function(e) assert(e:match(pat)) end, required) - assert(ok, "site.conf error: expected `" .. varname .. "' to be a string array matching pattern `" .. pat .. "'") + local var, conf_name = loadvar(varname) + local ok, var = pcall(__need_array_from_var, var, varname, function(e) assert(e:match(pat)) end, required, conf_name) + assert(ok, conf_name.." error: expected `" .. varname .. "' to be a string array matching pattern `" .. pat .. "'") return var end function need_array_of(varname, array, required) - local ok, var = pcall(need_array, varname, function(e) assert_one_of(e, array) end,required) - assert(ok, "site.conf error: expected `" .. varname .. "' to be a subset of given array: " .. array_to_string(array)) + local var, conf_name = loadvar(varname) + local ok, var = pcall(__need_array_from_var, var, varname, function(e) assert_one_of(e, array) end, required, conf_name) + assert(ok, conf_name.." error: expected `" .. varname .. "' to be a subset of given array: " .. array_to_string(array)) + return var +end + +function in_domain(var) + forbid_in_site(var) + return var +end + +function in_site(var) + forbid_in_domain(var) return var end diff --git a/scripts/domain_config.lua b/scripts/domain_config.lua new file mode 100644 index 00000000..1e166f66 --- /dev/null +++ b/scripts/domain_config.lua @@ -0,0 +1,13 @@ +local function load_domain(domain_code) + local config = os.getenv('GLUON_SITEDIR') + + local function loader() + coroutine.yield('return ') + coroutine.yield(io.open(config .. '/domains/' .. domain_code .. '.conf'):read('*a')) + end + + -- setfenv doesn't work with Lua 5.2 anymore, but we're using 5.1 + return setfenv(assert(load(coroutine.wrap(loader), 'domains/' .. domain_code .. '.conf')), {})() +end + +return load_domain From 387bf99ab3f98860f2815c5925de63f2cea4f161 Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 03/13] treewide: forbid use of selected site variables in domain specific or site configs (v2) --- package/gluon-authorized-keys/check_site.lua | 2 +- package/gluon-autoupdater/check_site.lua | 12 +++--- package/gluon-client-bridge/check_site.lua | 8 ++-- .../check_site.lua | 4 +- .../check_site.lua | 4 +- package/gluon-core/check_site.lua | 43 ++++++++++--------- .../check_site.lua | 4 +- package/gluon-mesh-vpn-fastd/check_site.lua | 14 +++--- package/gluon-node-info/check_site.lua | 2 +- package/gluon-setup-mode/check_site.lua | 3 +- package/gluon-web-admin/check_site.lua | 6 +-- .../gluon-web-mesh-vpn-fastd/check_site.lua | 2 +- package/gluon-web-node-role/check_site.lua | 4 +- 13 files changed, 54 insertions(+), 54 deletions(-) diff --git a/package/gluon-authorized-keys/check_site.lua b/package/gluon-authorized-keys/check_site.lua index d1acfabe..4c4d0729 100644 --- a/package/gluon-authorized-keys/check_site.lua +++ b/package/gluon-authorized-keys/check_site.lua @@ -1 +1 @@ -need_string_array 'authorized_keys' +need_string_array(in_site('authorized_keys')) diff --git a/package/gluon-autoupdater/check_site.lua b/package/gluon-autoupdater/check_site.lua index f02d34c8..a89c172e 100644 --- a/package/gluon-autoupdater/check_site.lua +++ b/package/gluon-autoupdater/check_site.lua @@ -1,14 +1,14 @@ -need_string 'autoupdater.branch' +need_string(in_site('autoupdater.branch')) -local function check_branch(k, _) - assert_uci_name(k) +local function check_branch(k, _, conf_name) + assert_uci_name(k, conf_name) local prefix = string.format('autoupdater.branches[%q].', k) - need_string(prefix .. 'name') + need_string(in_site(prefix .. 'name')) need_string_array_match(prefix .. 'mirrors', '^http://') - need_number(prefix .. 'good_signatures') - need_string_array_match(prefix .. 'pubkeys', '^%x+$') + need_number(in_site(prefix .. 'good_signatures')) + need_string_array_match(in_site(prefix .. 'pubkeys'), '^%x+$') end need_table('autoupdater.branches', check_branch) diff --git a/package/gluon-client-bridge/check_site.lua b/package/gluon-client-bridge/check_site.lua index 34060f16..64f470cb 100644 --- a/package/gluon-client-bridge/check_site.lua +++ b/package/gluon-client-bridge/check_site.lua @@ -1,10 +1,10 @@ -need_string_match('next_node.mac', '^%x[02468aAcCeE]:%x%x:%x%x:%x%x:%x%x:%x%x$', false) +need_string_match(in_domain('next_node.mac'), '^%x[02468aAcCeE]:%x%x:%x%x:%x%x:%x%x:%x%x$', false) -if need_string_match('next_node.ip4', '^%d+.%d+.%d+.%d+$', false) then - need_string_match('prefix4', '^%d+.%d+.%d+.%d+/%d+$') +if need_string_match(in_domain('next_node.ip4'), '^%d+.%d+.%d+.%d+$', false) then + need_string_match(in_domain('prefix4'), '^%d+.%d+.%d+.%d+/%d+$') end -need_string_match('next_node.ip6', '^[%x:]+$', false) +need_string_match(in_domain('next_node.ip6'), '^[%x:]+$', false) for _, config in ipairs({'wifi24', 'wifi5'}) do diff --git a/package/gluon-config-mode-contact-info/check_site.lua b/package/gluon-config-mode-contact-info/check_site.lua index fe818616..cd86afea 100644 --- a/package/gluon-config-mode-contact-info/check_site.lua +++ b/package/gluon-config-mode-contact-info/check_site.lua @@ -1,3 +1,3 @@ -if need_table('config_mode', nil, false) and need_table('config_mode.owner', nil, false) then - need_boolean('config_mode.owner.obligatory', false) +if need_table(in_site('config_mode'), nil, false) and need_table(in_site('config_mode.owner'), nil, false) then + need_boolean(in_site('config_mode.owner.obligatory'), false) end diff --git a/package/gluon-config-mode-geo-location/check_site.lua b/package/gluon-config-mode-geo-location/check_site.lua index 509226fe..5654c8e6 100644 --- a/package/gluon-config-mode-geo-location/check_site.lua +++ b/package/gluon-config-mode-geo-location/check_site.lua @@ -1,3 +1,3 @@ -if need_table('config_mode', nil, false) and need_table('config_mode.geo_location', nil, false) then - need_boolean('config_mode.geo_location.show_altitude', false) +if need_table(in_site('config_mode'), nil, false) and need_table(in_site('config_mode.geo_location'), nil, false) then + need_boolean(in_site('config_mode.geo_location.show_altitude'), false) end diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua index 72fce8a4..6a48d2a3 100644 --- a/package/gluon-core/check_site.lua +++ b/package/gluon-core/check_site.lua @@ -1,36 +1,37 @@ -need_string 'site_code' -need_string 'site_name' -need_string_match('site_seed', '^' .. ('%x'):rep(64) .. '$') +need_string(in_site('site_code')) +need_string(in_site('site_name')) +need_string_match(in_site('site_seed'), '^' .. ('%x'):rep(64) .. '$') if need_table('opkg', nil, false) then need_string('opkg.lede', false) - function check_repo(k, _) + function check_repo(k, _, conf_name) -- this is not actually a uci name, but using the same naming rules here is fine - assert_uci_name(k) + assert_uci_name(k, conf_name) - need_string(string.format('opkg.extra[%q]', k)) + local path = string.format('opkg.extra[%q]', k) + need_string(path) end need_table('opkg.extra', check_repo, false) end -need_string('hostname_prefix', false) -need_string 'timezone' +need_string(in_site('hostname_prefix'), false) +need_string(in_site('timezone')) need_string_array('ntp_servers', false) -need_string_match('prefix6', '^[%x:]+/64$') +need_string_match(in_domain('prefix6'), '^[%x:]+/64$') for _, config in ipairs({'wifi24', 'wifi5'}) do if need_table(config, nil, false) then - need_string('regdom') -- regdom is only required when wifi24 or wifi5 is configured + need_string(in_site('regdom')) -- regdom is only required when wifi24 or wifi5 is configured need_number(config .. '.channel') local rates = {1000, 2000, 5500, 6000, 9000, 11000, 12000, 18000, 24000, 36000, 48000, 54000} - local supported_rates = need_array_of(config .. '.supported_rates', rates, false) + local supported_rates = need_array_of(in_site(config .. '.supported_rates'), rates, false) if supported_rates then need_array_of(config .. '.basic_rate', supported_rates, true) else @@ -39,36 +40,36 @@ for _, config in ipairs({'wifi24', 'wifi5'}) do end end -need_boolean('poe_passthrough', false) +need_boolean(in_site('poe_passthrough'), false) if need_table('dns', nil, false) then need_number('dns.cacheentries', false) need_string_array_match('dns.servers', '^[%x:]+$', true) end if need_table('next_node', nil, false) then - need_string_match('next_node.ip6', '^[%x:]+$', false) - need_string_match('next_node.ip4', '^%d+.%d+.%d+.%d+$', false) + need_string_match(in_domain('next_node.ip6'), '^[%x:]+$', false) + need_string_match(in_domain('next_node.ip4'), '^%d+.%d+.%d+.%d+$', false) end for _, config in ipairs({'wifi24', 'wifi5'}) do local rates = {1000, 2000, 5500, 6000, 9000, 11000, 12000, 18000, 24000, 36000, 48000, 54000} - rates = need_array_of(config .. '.supported_rates', rates, false) or rates + rates = need_array_of(in_site(config .. '.supported_rates'), rates, false) or rates if need_table(config .. '.ibss', nil, false) then - need_string(config .. '.ibss.ssid') - need_string_match(config .. '.ibss.bssid', '^%x[02468aAcCeE]:%x%x:%x%x:%x%x:%x%x:%x%x$') + need_string(in_domain(config .. '.ibss.ssid')) + need_string_match(in_domain(config .. '.ibss.bssid'), '^%x[02468aAcCeE]:%x%x:%x%x:%x%x:%x%x:%x%x$') need_one_of(config .. '.ibss.mcast_rate', rates, false) need_number(config .. '.ibss.vlan', false) need_boolean(config .. '.ibss.disabled', false) end if need_table(config .. '.mesh', nil, false) then - need_string(config .. '.mesh.id') + need_string(in_domain(config .. '.mesh.id')) need_one_of(config .. '.mesh.mcast_rate', rates, false) need_boolean(config .. '.mesh.disabled', false) end end -need_boolean('mesh_on_wan', false) -need_boolean('mesh_on_lan', false) -need_boolean('single_as_lan', false) +need_boolean(in_site('mesh_on_wan'), false) +need_boolean(in_site('mesh_on_lan'), false) +need_boolean(in_site('single_as_lan'), false) diff --git a/package/gluon-ebtables-source-filter/check_site.lua b/package/gluon-ebtables-source-filter/check_site.lua index 815c7296..d0e7ccfd 100644 --- a/package/gluon-ebtables-source-filter/check_site.lua +++ b/package/gluon-ebtables-source-filter/check_site.lua @@ -1,2 +1,2 @@ -need_string_match('prefix4', '^%d+.%d+.%d+.%d+/%d+$', false) -need_string_array_match('extra_prefixes6', '^[%x:]+/%d+$', false) +need_string_match(in_domain('prefix4'), '^%d+.%d+.%d+.%d+/%d+$', false) +need_string_array_match(in_domain('extra_prefixes6'), '^[%x:]+/%d+$', false) diff --git a/package/gluon-mesh-vpn-fastd/check_site.lua b/package/gluon-mesh-vpn-fastd/check_site.lua index 64da9c88..2f846b7c 100644 --- a/package/gluon-mesh-vpn-fastd/check_site.lua +++ b/package/gluon-mesh-vpn-fastd/check_site.lua @@ -1,23 +1,23 @@ local fastd_methods = {'salsa2012+gmac', 'salsa2012+umac', 'null+salsa2012+gmac', 'null+salsa2012+umac', 'null'} need_array_of('mesh_vpn.fastd.methods', fastd_methods) -need_boolean('mesh_vpn.fastd.configurable', false) +need_boolean(in_site('mesh_vpn.fastd.configurable'), false) -need_one_of('mesh_vpn.fastd.syslog_level', {'error', 'warn', 'info', 'verbose', 'debug', 'debug2'}, false) +need_one_of(in_site('mesh_vpn.fastd.syslog_level'), {'error', 'warn', 'info', 'verbose', 'debug', 'debug2'}, false) local function check_peer(prefix) - return function(k, _) - assert_uci_name(k) + return function(k, _, conf_name) + assert_uci_name(k, conf_name) local table = string.format('%s[%q].', prefix, k) need_string_match(table .. 'key', '^%x+$') - need_string_array(table .. 'remotes') + need_string_array(in_domain(table .. 'remotes')) end end local function check_group(prefix) - return function(k, _) - assert_uci_name(k) + return function(k, _, conf_name) + assert_uci_name(k, conf_name) local table = string.format('%s[%q].', prefix, k) diff --git a/package/gluon-node-info/check_site.lua b/package/gluon-node-info/check_site.lua index 7e50edfc..b7c4226d 100644 --- a/package/gluon-node-info/check_site.lua +++ b/package/gluon-node-info/check_site.lua @@ -1 +1 @@ -need_string('roles.default', false) +need_string(in_site('roles.default'), false) diff --git a/package/gluon-setup-mode/check_site.lua b/package/gluon-setup-mode/check_site.lua index 07baaad3..b1df6a68 100644 --- a/package/gluon-setup-mode/check_site.lua +++ b/package/gluon-setup-mode/check_site.lua @@ -1,2 +1 @@ -need_boolean('setup_mode.skip', false) - +need_boolean(in_site('setup_mode.skip'), false) diff --git a/package/gluon-web-admin/check_site.lua b/package/gluon-web-admin/check_site.lua index 7fdce6fb..8c88d147 100644 --- a/package/gluon-web-admin/check_site.lua +++ b/package/gluon-web-admin/check_site.lua @@ -1,4 +1,4 @@ -if need_table('config_mode', nil, false) and need_table('config_mode.remote_login', nil, false) then - need_boolean('config_mode.remote_login.show_password_form', false) - need_number('config_mode.remote_login.min_password_length', false) +if need_table(in_site('config_mode'), nil, false) and need_table(in_site('config_mode.remote_login'), nil, false) then + need_boolean(in_site('config_mode.remote_login.show_password_form'), false) + need_number(in_site('config_mode.remote_login.min_password_length'), false) end diff --git a/package/gluon-web-mesh-vpn-fastd/check_site.lua b/package/gluon-web-mesh-vpn-fastd/check_site.lua index b9e41e11..1704204a 100644 --- a/package/gluon-web-mesh-vpn-fastd/check_site.lua +++ b/package/gluon-web-mesh-vpn-fastd/check_site.lua @@ -1,2 +1,2 @@ -assert(need_boolean('mesh_vpn.fastd.configurable') == true, +assert(need_boolean(in_site('mesh_vpn.fastd.configurable')) == true, "site.conf error: expected `mesh_vpn.fastd.configurable' to be true") diff --git a/package/gluon-web-node-role/check_site.lua b/package/gluon-web-node-role/check_site.lua index ab01eeb5..747915be 100644 --- a/package/gluon-web-node-role/check_site.lua +++ b/package/gluon-web-node-role/check_site.lua @@ -1,2 +1,2 @@ -need_string 'roles.default' -need_string_array 'roles.list' +need_string(in_site('roles.default')) +need_string_array(in_site('roles.list')) From b3c9ac8bce78d522b3b709dabb55e960cde03358 Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 04/13] scripts: check_site_lib: need_table() now merges all keys before calling subcheck(...) This also introduces an api change to the subcheck()! Before: -> subcheck(key, value, conf_name) After: -> subcheck(key, conf_name) The idea is, that it's hard to submit a value, which should be then checked again. It's wouldn't be clear (after merging) from which config the value is, and so an helpful error message would be impossible. --- package/gluon-autoupdater/check_site.lua | 2 +- package/gluon-core/check_site.lua | 2 +- package/gluon-mesh-vpn-fastd/check_site.lua | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package/gluon-autoupdater/check_site.lua b/package/gluon-autoupdater/check_site.lua index a89c172e..2ed17c45 100644 --- a/package/gluon-autoupdater/check_site.lua +++ b/package/gluon-autoupdater/check_site.lua @@ -1,6 +1,6 @@ need_string(in_site('autoupdater.branch')) -local function check_branch(k, _, conf_name) +local function check_branch(k, conf_name) assert_uci_name(k, conf_name) local prefix = string.format('autoupdater.branches[%q].', k) diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua index 6a48d2a3..03439328 100644 --- a/package/gluon-core/check_site.lua +++ b/package/gluon-core/check_site.lua @@ -5,7 +5,7 @@ need_string_match(in_site('site_seed'), '^' .. ('%x'):rep(64) .. '$') if need_table('opkg', nil, false) then need_string('opkg.lede', false) - function check_repo(k, _, conf_name) + function check_repo(k, conf_name) -- this is not actually a uci name, but using the same naming rules here is fine assert_uci_name(k, conf_name) diff --git a/package/gluon-mesh-vpn-fastd/check_site.lua b/package/gluon-mesh-vpn-fastd/check_site.lua index 2f846b7c..f2abf83c 100644 --- a/package/gluon-mesh-vpn-fastd/check_site.lua +++ b/package/gluon-mesh-vpn-fastd/check_site.lua @@ -5,7 +5,7 @@ need_boolean(in_site('mesh_vpn.fastd.configurable'), false) need_one_of(in_site('mesh_vpn.fastd.syslog_level'), {'error', 'warn', 'info', 'verbose', 'debug', 'debug2'}, false) local function check_peer(prefix) - return function(k, _, conf_name) + return function(k, conf_name) assert_uci_name(k, conf_name) local table = string.format('%s[%q].', prefix, k) @@ -16,7 +16,7 @@ local function check_peer(prefix) end local function check_group(prefix) - return function(k, _, conf_name) + return function(k, conf_name) assert_uci_name(k, conf_name) local table = string.format('%s[%q].', prefix, k) From 5999fdb603ae3574eac36f2b110eb3b23e53fdaf Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 05/13] gluon-core: merge site.json and domain.json in site lua module --- package/gluon-core/check_site.lua | 3 ++ .../luasrc/usr/lib/lua/gluon/site.lua | 34 ++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua index 03439328..ed3f0337 100644 --- a/package/gluon-core/check_site.lua +++ b/package/gluon-core/check_site.lua @@ -2,6 +2,9 @@ need_string(in_site('site_code')) need_string(in_site('site_name')) need_string_match(in_site('site_seed'), '^' .. ('%x'):rep(64) .. '$') +-- TODO: it should be checked for existance! +need_string(in_site('default_domain_code')) + if need_table('opkg', nil, false) then need_string('opkg.lede', false) diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/site.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/site.lua index 56491763..38d6ad67 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/site.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/site.lua @@ -1,11 +1,10 @@ -local site = (function() - local config = '/lib/gluon/site.json' +local function read_json(path) local json = require 'luci.jsonc' local decoder = json.new() local sink = decoder:sink() - local file = assert(io.open(config)) + local file = assert(io.open(path)) while true do local chunk = file:read(2048) @@ -16,11 +15,36 @@ local site = (function() file:close() return assert(decoder:get()) -end)() +end + +local site = read_json('/lib/gluon/site.json') +local domain = (function(site) + local uci = require('simple-uci').cursor() + local fs = require "nixio.fs" + local sname = uci:get_first('gluon', 'system') + + local dc = uci:get('gluon', sname, 'domain_code') or '' + + if fs.stat('/lib/gluon/domains/'..dc..'.json', 'type')~='reg' then + dc = site['default_domain_code'] + end + + return read_json('/lib/gluon/domains/'..dc..'.json') +end)(site) local wrap +local function merge(t1, t2) + for k, v in pairs(t2) do + if (type(v) == "table") and (type(t1[k] or false) == "table") then + merge(t1[k], t2[k]) + else + t1[k] = v + end + end + return t1 +end local function index(t, k) local v = getmetatable(t).value @@ -58,4 +82,4 @@ end module 'gluon.site' -return wrap(site, _M) +return wrap(merge(site, domain), _M) From a73ae6c16d5e78d6922da75237f15b6d7459bf1a Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 06/13] gluon-core: add script /lib/gluon/domain_changed.sh --- package/gluon-core/files/lib/gluon/domain_changed.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100755 package/gluon-core/files/lib/gluon/domain_changed.sh diff --git a/package/gluon-core/files/lib/gluon/domain_changed.sh b/package/gluon-core/files/lib/gluon/domain_changed.sh new file mode 100755 index 00000000..a8ed75a7 --- /dev/null +++ b/package/gluon-core/files/lib/gluon/domain_changed.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +domain_code=$(uci get gluon.system.domain_code) + +[ -f /lib/gluon/domains/${domain_code}.json ] || (echo "file not found: /lib/gluon/domains/${domain_code}.json" >&2; exit 1) || exit 1 + +for s in /lib/gluon/upgrade/*; do + echo -n ${s}: + (${s} && echo " ok") || echo " error" +done From 0189f350f94b8e733c9d8531ab760a67ff787731 Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 07/13] libgluonutil: merge domain and site configs --- package/libgluonutil/Makefile | 2 +- package/libgluonutil/src/CMakeLists.txt | 5 +- package/libgluonutil/src/FindUCI.cmake | 21 ++++ package/libgluonutil/src/libgluonutil.c | 151 +++++++++++++++++++++++- package/libgluonutil/src/libgluonutil.h | 14 +++ 5 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 package/libgluonutil/src/FindUCI.cmake diff --git a/package/libgluonutil/Makefile b/package/libgluonutil/Makefile index 489a9ba9..2536727c 100644 --- a/package/libgluonutil/Makefile +++ b/package/libgluonutil/Makefile @@ -16,7 +16,7 @@ define Package/libgluonutil SECTION:=libs CATEGORY:=Libraries TITLE:=Gluon utility library - DEPENDS:=+libjson-c + DEPENDS:=+libjson-c +libuci endef CMAKE_OPTIONS += \ diff --git a/package/libgluonutil/src/CMakeLists.txt b/package/libgluonutil/src/CMakeLists.txt index ba92a3e1..ac8c0c49 100644 --- a/package/libgluonutil/src/CMakeLists.txt +++ b/package/libgluonutil/src/CMakeLists.txt @@ -7,14 +7,15 @@ project(libgluonutil C) set(LIBDIR "lib${LIB_SUFFIX}") find_package(JSON_C REQUIRED) +find_package(UCI REQUIRED) set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS _GNU_SOURCE) add_library(gluonutil SHARED libgluonutil.c) set_property(TARGET gluonutil PROPERTY COMPILE_FLAGS "-Wall -std=c99 ${JSON_C_CFLAGS_OTHER}") set_property(TARGET gluonutil PROPERTY LINK_FLAGS "${JSON_C_LDFLAGS_OTHER}") -set_property(TARGET gluonutil APPEND PROPERTY INCLUDE_DIRECTORIES ${JSON_C_INCLUDE_DIR}) -target_link_libraries(gluonutil ${JSON_C_LIBRARIES}) +set_property(TARGET gluonutil APPEND PROPERTY INCLUDE_DIRECTORIES ${JSON_C_INCLUDE_DIR} ${UCI_INCLUDE_DIR}) +target_link_libraries(gluonutil ${JSON_C_LIBRARIES} ${UCI_LIBRARIES}) install(TARGETS gluonutil ARCHIVE DESTINATION ${LIBDIR} LIBRARY DESTINATION ${LIBDIR} diff --git a/package/libgluonutil/src/FindUCI.cmake b/package/libgluonutil/src/FindUCI.cmake new file mode 100644 index 00000000..820bc09b --- /dev/null +++ b/package/libgluonutil/src/FindUCI.cmake @@ -0,0 +1,21 @@ +# UCI_FOUND - true if library and headers were found +# UCI_INCLUDE_DIRS - include directories +# UCI_LIBRARIES - library directories + +find_package(PkgConfig) +pkg_check_modules(PC_UCI QUIET uci) + +find_path(UCI_INCLUDE_DIR uci.h + HINTS ${PC_UCI_INCLUDEDIR} ${PC_UCI_INCLUDE_DIRS}) + +find_library(UCI_LIBRARY NAMES uci libuci + HINTS ${PC_UCI_LIBDIR} ${PC_UCI_LIBRARY_DIRS}) + +set(UCI_LIBRARIES ${UCI_LIBRARY}) +set(UCI_INCLUDE_DIRS ${UCI_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(UCI DEFAULT_MSG UCI_LIBRARY UCI_INCLUDE_DIR) + +mark_as_advanced(UCI_INCLUDE_DIR UCI_LIBRARY) diff --git a/package/libgluonutil/src/libgluonutil.c b/package/libgluonutil/src/libgluonutil.c index db46b9c9..36eecbc2 100644 --- a/package/libgluonutil/src/libgluonutil.c +++ b/package/libgluonutil/src/libgluonutil.c @@ -31,7 +31,41 @@ #include #include #include +#include +#include +/** + * Merges two JSON objects + * + * On conflicts, object a will be preferred. + * + * Internally, this functions merges all entries from object a into object b, + * so merging a small object a with a big object b is faster than vice-versa. + */ +static struct json_object * merge_json(struct json_object *a, struct json_object *b) { + if (!json_object_is_type(a, json_type_object) || !json_object_is_type(b, json_type_object)) { + json_object_put(b); + return a; + } + + json_object_object_foreach(a, key, val_a) { + struct json_object *val_b; + + json_object_get(val_a); + + if (!json_object_object_get_ex(b, key, &val_b)) { + json_object_object_add(b, key, val_a); + continue; + } + + json_object_get(val_b); + + json_object_object_add(b, key, merge_json(val_a, val_b)); + } + + json_object_put(a); + return b; +} char * gluonutil_read_line(const char *filename) { FILE *f = fopen(filename, "r"); @@ -140,7 +174,122 @@ bool gluonutil_get_node_prefix6(struct in6_addr *prefix) { return true; } +char * get_selected_domain_code(struct json_object * base) { + char * domain_path_fmt = "/lib/gluon/domains/%s.json"; + char domain_path[strlen(domain_path_fmt) + 256]; + const char * domain_code; + + struct uci_context *ctx = uci_alloc_context(); + if (!ctx) + goto uci_fail; + + ctx->flags &= ~UCI_FLAG_STRICT; + + struct uci_package *p; + if (uci_load(ctx, "gluon", &p)) + goto uci_fail; + + struct uci_section *s = uci_lookup_section(ctx, p, "system"); + if (!s) + goto uci_fail; + + domain_code = uci_lookup_option_string(ctx, s, "domain_code"); + + if (!domain_code) + goto uci_fail; + + snprintf(domain_path, sizeof domain_path, domain_path_fmt, domain_code); + + if (access(domain_path, R_OK) != -1) { + // ${domain_code}.conf exists and is accessible + char * domain_code_cpy = strndup(domain_code, 256); // copy before free + uci_free_context(ctx); + return domain_code_cpy; + } + +uci_fail: + if (ctx) + uci_free_context(ctx); + + json_object * default_domain_code; + + // it's okay to pass base == NULL to json_object_object_get_ex() + if (!json_object_object_get_ex(base, "default_domain_code", &default_domain_code)) + return NULL; + + domain_code = json_object_get_string(default_domain_code); + + if (!domain_code) + return NULL; + + // the gluon build environment should ensure, that this filename exists, + // but to be sure, we check here again. + snprintf(domain_path, sizeof domain_path, domain_path_fmt, domain_code); + + if (access(domain_path, R_OK) == -1) + return NULL; + + // create a copy so site could be freed before domain_code + return strndup(domain_code, 256); +} + +/** + * Get selected domain code + * + * - If NULL is passed to the site parameter, internally only the base part + * (without domain config) is loaded, which is more efficient than calling + * gluonutil_load_site_config() for this job only. Nevertheless if you already + * have an instance of a site object then you should pass it here. + * - Returned domain code string has to be freed after use + * - Returns NULL in case of error + * - If a domain code is returned, it's ensured that the corresponding config + * in /lib/gluon/domains/ exists. + */ +char * gluonutil_get_selected_domain_code(struct json_object * site) { + if (site) + // If the user already has allocated a whole site object, it makes no sense + // to load the base object. Taking the site object (merged from domain and + // base) should be fine here. + return get_selected_domain_code(site); + + // load base + struct json_object * base = json_object_from_file("/lib/gluon/site.json"); + + if (!base) + return NULL; + + return get_selected_domain_code(base); +} struct json_object * gluonutil_load_site_config(void) { - return json_object_from_file("/lib/gluon/site.json"); + // load base + struct json_object * base = json_object_from_file("/lib/gluon/site.json"); + + if (!base) + return NULL; + + // load domain + char * domain_path_fmt = "/lib/gluon/domains/%s.json"; + char domain_path[strlen(domain_path_fmt) + 256]; + char * domain_code = get_selected_domain_code(base); + + if (!domain_code) { + // something went horribly wrong here + json_object_put(base); // free base + return NULL; + } + + snprintf(domain_path, sizeof domain_path, domain_path_fmt, domain_code); + + free(domain_code); + + struct json_object * domain = json_object_from_file(domain_path); + + if (!domain) { + json_object_put(base); + return NULL; + } + + // finally merge them + return merge_json(domain, base); } diff --git a/package/libgluonutil/src/libgluonutil.h b/package/libgluonutil/src/libgluonutil.h index b2f90d69..d464005c 100644 --- a/package/libgluonutil/src/libgluonutil.h +++ b/package/libgluonutil/src/libgluonutil.h @@ -42,4 +42,18 @@ struct json_object * gluonutil_wrap_and_free_string(char *str); struct json_object * gluonutil_load_site_config(void); +/** + * Get selected domain code + * + * - If NULL is passed to the site parameter, internally only the base part + * (without domain config) is loaded, which is more efficient than calling + * gluonutil_load_site_config() for this job only. Nevertheless if you already + * have an instance of a site object then you should pass it here. + * - Returned domain code string has to be freed after use + * - Returns NULL in case of error + * - If a domain code is returned, it's ensured that the corresponding config + * in /lib/gluon/domains/ exists. + */ +char * gluonutil_get_selected_domain_code(struct json_object * site); + #endif /* _LIBGLUON_LIBGLUON_H_ */ From c5ca75d0dd119fcfc8f3593dfcab033cfd06da32 Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 08/13] gluon-core: add util gluon-print-site to print merged site config --- package/gluon-core/luasrc/usr/bin/gluon-print-site | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 package/gluon-core/luasrc/usr/bin/gluon-print-site diff --git a/package/gluon-core/luasrc/usr/bin/gluon-print-site b/package/gluon-core/luasrc/usr/bin/gluon-print-site new file mode 100755 index 00000000..3cec78de --- /dev/null +++ b/package/gluon-core/luasrc/usr/bin/gluon-print-site @@ -0,0 +1,5 @@ +#!/usr/bin/lua +local jsonc = require 'luci.jsonc' +local site = require 'gluon.site' + +print(jsonc.stringify(site(), true)) From d776bf7d1abe7cb7f7f6eeb20501620f5b6fd1bf Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 09/13] gluon-site: ensure default_domain_code config exists --- package/gluon-core/check_site.lua | 1 - package/gluon-site/Makefile | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua index ed3f0337..9807a20e 100644 --- a/package/gluon-core/check_site.lua +++ b/package/gluon-core/check_site.lua @@ -2,7 +2,6 @@ need_string(in_site('site_code')) need_string(in_site('site_name')) need_string_match(in_site('site_seed'), '^' .. ('%x'):rep(64) .. '$') --- TODO: it should be checked for existance! need_string(in_site('default_domain_code')) if need_table('opkg', nil, false) then diff --git a/package/gluon-site/Makefile b/package/gluon-site/Makefile index 8118b5f8..3eac0048 100644 --- a/package/gluon-site/Makefile +++ b/package/gluon-site/Makefile @@ -47,6 +47,8 @@ endef define Build/Compile GLUON_SITEDIR='$(call qstrip,$(CONFIG_GLUON_SITEDIR))' lua -e 'print(require("cjson").encode(assert(dofile("../../scripts/site_config.lua"))))' > $(PKG_BUILD_DIR)/site.json ls $(call qstrip,$(CONFIG_GLUON_SITEDIR))/domains/*.conf > /dev/null # at least one domain cfg has to exist + GLUON_SITEDIR='$(call qstrip,$(CONFIG_GLUON_SITEDIR))' lua -e 'print(assert(dofile("../../scripts/site_config.lua")).default_domain_code)' > $(PKG_BUILD_DIR)/default_domain_code + ls '$(call qstrip,$(CONFIG_GLUON_SITEDIR))'/domains/$$$$(cat $(PKG_BUILD_DIR)/default_domain_code).conf # ensure default_domain_code exists for domain_cfg in `find $(call qstrip,$(CONFIG_GLUON_SITEDIR))/domains/ -iname \*.conf -printf "%f\n"`; do dc=$$$${domain_cfg%.conf}; GLUON_SITEDIR='$(call qstrip,$(CONFIG_GLUON_SITEDIR))' lua -e 'print(require("cjson").encode(assert(dofile("../../scripts/domain_config.lua")("'$$$${dc}'"))))' > $(PKG_BUILD_DIR)/domains/$$$${dc}.json; done $(call GluonBuildI18N,gluon-site,$(GLUON_SITEDIR)/i18n) endef From 4facaf6846581582ff7c8f6b801d81f62ab4ff14 Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 10/13] gluon-respondd: add system.domain_code to respondd provider "nodeinfo" --- package/gluon-respondd/src/respondd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package/gluon-respondd/src/respondd.c b/package/gluon-respondd/src/respondd.c index a31693e6..ea1fe242 100644 --- a/package/gluon-respondd/src/respondd.c +++ b/package/gluon-respondd/src/respondd.c @@ -66,6 +66,11 @@ static struct json_object * get_site_code(void) { return ret; } +static struct json_object * get_domain_code(void) { + char * domain_code = gluonutil_get_selected_domain_code(NULL); + return gluonutil_wrap_and_free_string(domain_code); +} + static struct json_object * get_hostname(void) { struct json_object *ret = NULL; @@ -122,6 +127,7 @@ static struct json_object * respondd_provider_nodeinfo(void) { struct json_object *system = json_object_new_object(); json_object_object_add(system, "site_code", get_site_code()); + json_object_object_add(system, "domain_code", get_domain_code()); json_object_object_add(ret, "system", system); return ret; From bf3446598bb1b345f0e7128807a68043c7130b88 Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 11/13] gluon-core: move from site_seed to domain_seed --- docs/site-example/site.conf | 2 +- docs/user/site.rst | 2 +- package/gluon-core/check_site.lua | 2 +- package/gluon-core/files/lib/netifd/proto/gluon_wired.sh | 2 +- package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/site-example/site.conf b/docs/site-example/site.conf index 3d317cbf..a152eca6 100644 --- a/docs/site-example/site.conf +++ b/docs/site-example/site.conf @@ -18,7 +18,7 @@ -- 32 bytes of random data, encoded in hexadecimal -- Must be the same for all nodes in one mesh domain -- Can be generated using: echo $(hexdump -v -n 32 -e '1/1 "%02x"' Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 12/13] gluon-core: add domain aliases and pretty name --- package/gluon-core/check_site.lua | 11 +++++++++++ .../luasrc/usr/lib/lua/gluon/site.lua | 6 +++++- package/gluon-site/Makefile | 10 +++++++++- package/libgluonutil/src/libgluonutil.c | 19 ++++++++++++++++++- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua index e49f8b03..fba23456 100644 --- a/package/gluon-core/check_site.lua +++ b/package/gluon-core/check_site.lua @@ -4,6 +4,17 @@ need_string_match(in_domain('domain_seed'), '^' .. ('%x'):rep(64) .. '$') need_string(in_site('default_domain_code')) +need_string(in_domain('domain_name')) + +function check_alias(k, conf_name) + assert_uci_name(k, conf_name) + + local path = string.format('domain_aliases[%q]', k) + need_string(in_domain(path)) +end + +need_table(in_domain('domain_aliases'), check_alias, false) + if need_table('opkg', nil, false) then need_string('opkg.lede', false) diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/site.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/site.lua index 38d6ad67..3846b3ab 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/site.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/site.lua @@ -29,7 +29,11 @@ local domain = (function(site) dc = site['default_domain_code'] end - return read_json('/lib/gluon/domains/'..dc..'.json') + local domain = read_json('/lib/gluon/domains/'..dc..'.json') + if domain['domain_aliases'] and domain['domain_aliases'][dc] then + domain['domain_name'] = domain['domain_aliases'][dc] + end + return domain end)(site) diff --git a/package/gluon-site/Makefile b/package/gluon-site/Makefile index 3eac0048..8b67b1d7 100644 --- a/package/gluon-site/Makefile +++ b/package/gluon-site/Makefile @@ -49,7 +49,15 @@ define Build/Compile ls $(call qstrip,$(CONFIG_GLUON_SITEDIR))/domains/*.conf > /dev/null # at least one domain cfg has to exist GLUON_SITEDIR='$(call qstrip,$(CONFIG_GLUON_SITEDIR))' lua -e 'print(assert(dofile("../../scripts/site_config.lua")).default_domain_code)' > $(PKG_BUILD_DIR)/default_domain_code ls '$(call qstrip,$(CONFIG_GLUON_SITEDIR))'/domains/$$$$(cat $(PKG_BUILD_DIR)/default_domain_code).conf # ensure default_domain_code exists - for domain_cfg in `find $(call qstrip,$(CONFIG_GLUON_SITEDIR))/domains/ -iname \*.conf -printf "%f\n"`; do dc=$$$${domain_cfg%.conf}; GLUON_SITEDIR='$(call qstrip,$(CONFIG_GLUON_SITEDIR))' lua -e 'print(require("cjson").encode(assert(dofile("../../scripts/domain_config.lua")("'$$$${dc}'"))))' > $(PKG_BUILD_DIR)/domains/$$$${dc}.json; done + rm -f $(PKG_BUILD_DIR)/domains/*.json + for domain_cfg in `find $(call qstrip,$(CONFIG_GLUON_SITEDIR))/domains/ -iname \*.conf -printf "%f\n"`; do \ + dc=$$$${domain_cfg%.conf}; \ + GLUON_SITEDIR='$(call qstrip,$(CONFIG_GLUON_SITEDIR))' lua -e 'print(require("cjson").encode(assert(dofile("../../scripts/domain_config.lua")("'$$$${dc}'"))))' > $(PKG_BUILD_DIR)/domains/$$$${dc}.json; \ + aliases=$$$$(GLUON_SITEDIR='$(call qstrip,$(CONFIG_GLUON_SITEDIR))' lua -e 'for alias_name, _ in pairs(dofile("../../scripts/domain_config.lua")("'$$$${dc}'")["domain_aliases"] or {}) do print(alias_name.." ") end'); \ + for alias in $$$${aliases}; do \ + ln -s $$$${dc}.json $(PKG_BUILD_DIR)/domains/$$$${alias}.json; \ + done; \ + done $(call GluonBuildI18N,gluon-site,$(GLUON_SITEDIR)/i18n) endef diff --git a/package/libgluonutil/src/libgluonutil.c b/package/libgluonutil/src/libgluonutil.c index 36eecbc2..8510ef2a 100644 --- a/package/libgluonutil/src/libgluonutil.c +++ b/package/libgluonutil/src/libgluonutil.c @@ -281,7 +281,6 @@ struct json_object * gluonutil_load_site_config(void) { snprintf(domain_path, sizeof domain_path, domain_path_fmt, domain_code); - free(domain_code); struct json_object * domain = json_object_from_file(domain_path); @@ -290,6 +289,24 @@ struct json_object * gluonutil_load_site_config(void) { return NULL; } + json_object * aliases; + + // it's okay to pass base == NULL to json_object_object_get_ex() + if (!json_object_object_get_ex(domain, "domain_aliases", &aliases)) + goto skip_name_replacement; + + json_object * aliased_domain_name; + + if (!json_object_object_get_ex(aliases, domain_code, &aliased_domain_name)) + goto skip_name_replacement; + + // freeing of old value is done inside json_object_object_add() + json_object_object_add(domain, "domain_name", json_object_get(aliased_domain_name)); + +skip_name_replacement: + + free(domain_code); + // finally merge them return merge_json(domain, base); } From 33765c73345df7896ec689e631d96d8ffbf514d0 Mon Sep 17 00:00:00 2001 From: lemoer Date: Sat, 28 Oct 2017 17:05:53 +0200 Subject: [PATCH 13/13] gluon-status-page: show current domain name --- package/gluon-status-page/src/js/lib/gui/nodeinfo.js | 1 + 1 file changed, 1 insertion(+) diff --git a/package/gluon-status-page/src/js/lib/gui/nodeinfo.js b/package/gluon-status-page/src/js/lib/gui/nodeinfo.js index 4fc08123..920b0f5a 100644 --- a/package/gluon-status-page/src/js/lib/gui/nodeinfo.js +++ b/package/gluon-status-page/src/js/lib/gui/nodeinfo.js @@ -53,6 +53,7 @@ define(["lib/helper"], function (Helper) { dlEntry(list, nodeInfo, "software.fastd.enabled", Helper._("Mesh VPN"), enabledDisabled) dlEntry(list, nodeInfo, "software.autoupdater.enabled", Helper._("Automatic updates"), enabledDisabled) dlEntry(list, nodeInfo, "software.autoupdater.branch", Helper._("Branch")) + dlEntry(list, nodeInfo, "system.domain_code", Helper._("Domain")) el.appendChild(list) }