summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/luasrc/model
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2018-04-19 11:42:12 +0200
committerJo-Philipp Wich <jo@mein.io>2018-04-19 11:42:12 +0200
commit9b22c9c1e1290f077297b14b835b3b9085b48bde (patch)
treec55a9316a5d8aedead610408315f6835d30510fb /modules/luci-base/luasrc/model
parentfc8f825e2f6fedcc149fb3aafd7f6aa3eb4dcad7 (diff)
luci-base: implement session handling in luci.model.uci
Introduce luci.model.uci.set_session_id() and luci.model.uci.get_session_id() to set and get the effective session ID respectively. When a session ID is set, it is sent as `ubus_rpc_session` attribute to rpcd, causing it to use per-session change directories, isolating LuCI changes from the global system uci state. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'modules/luci-base/luasrc/model')
-rw-r--r--modules/luci-base/luasrc/model/uci.lua50
-rw-r--r--modules/luci-base/luasrc/model/uci.luadoc299
2 files changed, 193 insertions, 156 deletions
diff --git a/modules/luci-base/luasrc/model/uci.lua b/modules/luci-base/luasrc/model/uci.lua
index 0e3950c0b..fc2a605b3 100644
--- a/modules/luci-base/luasrc/model/uci.lua
+++ b/modules/luci-base/luasrc/model/uci.lua
@@ -32,6 +32,15 @@ local ERRSTR = {
"Connection failed"
}
+local session_id = nil
+
+local function call(cmd, args)
+ if type(args) == "table" and session_id then
+ args.ubus_rpc_session = session_id
+ end
+ return util.ubus("uci", cmd, args)
+end
+
function cursor()
return _M
@@ -54,6 +63,10 @@ function get_savedir(self)
return "/tmp/.uci"
end
+function get_session_id(self)
+ return session_id
+end
+
function set_confdir(self, directory)
return false
end
@@ -62,6 +75,11 @@ function set_savedir(self, directory)
return false
end
+function set_session_id(self, id)
+ session_id = id
+ return true
+end
+
function load(self, config)
return true
@@ -77,7 +95,7 @@ end
function changes(self, config)
- local rv = util.ubus("uci", "changes", { config = config })
+ local rv = call("changes", { config = config })
local res = {}
if type(rv) == "table" and type(rv.changes) == "table" then
@@ -116,12 +134,12 @@ end
function revert(self, config)
- local _, err = util.ubus("uci", "revert", { config = config })
+ local _, err = call("revert", { config = config })
return (err == nil), ERRSTR[err]
end
function commit(self, config)
- local _, err = util.ubus("uci", "commit", { config = config })
+ local _, err = call("commit", { config = config })
return (err == nil), ERRSTR[err]
end
@@ -133,7 +151,7 @@ function apply(self, configs, command)
if type(configs) == "table" then
for _, config in ipairs(configs) do
- util.ubus("service", "event", {
+ call("service", "event", {
type = "config.change",
data = { package = config }
})
@@ -145,7 +163,7 @@ end
function foreach(self, config, stype, callback)
if type(callback) == "function" then
- local rv, err = util.ubus("uci", "get", {
+ local rv, err = call("get", {
config = config,
type = stype
})
@@ -186,7 +204,7 @@ local function _get(self, operation, config, section, option)
if section == nil then
return nil
elseif type(option) == "string" and option:byte(1) ~= 46 then
- local rv, err = util.ubus("uci", operation, {
+ local rv, err = call(operation, {
config = config,
section = section,
option = option
@@ -220,7 +238,7 @@ function get_state(self, ...)
end
function get_all(self, config, section)
- local rv, err = util.ubus("uci", "get", {
+ local rv, err = call("get", {
config = config,
section = section
})
@@ -271,7 +289,7 @@ end
function section(self, config, stype, name, values)
- local rv, err = util.ubus("uci", "add", {
+ local rv, err = call("add", {
config = config,
type = stype,
name = name,
@@ -297,7 +315,7 @@ function set(self, config, section, option, value)
local sname, err = self:section(config, option, section)
return (not not sname), err
else
- local _, err = util.ubus("uci", "set", {
+ local _, err = call("set", {
config = config,
section = section,
values = { [option] = value }
@@ -319,7 +337,7 @@ function set_list(self, config, section, option, value)
end
function tset(self, config, section, values)
- local _, err = util.ubus("uci", "set", {
+ local _, err = call("set", {
config = config,
section = section,
values = values
@@ -353,7 +371,7 @@ function reorder(self, config, section, index)
return false, "Invalid argument"
end
- local _, err = util.ubus("uci", "order", {
+ local _, err = call("order", {
config = config,
sections = sections
})
@@ -363,7 +381,7 @@ end
function delete(self, config, section, option)
- local _, err = util.ubus("uci", "delete", {
+ local _, err = call("delete", {
config = config,
section = section,
option = option
@@ -374,13 +392,13 @@ end
function delete_all(self, config, stype, comparator)
local _, err
if type(comparator) == "table" then
- _, err = util.ubus("uci", "delete", {
+ _, err = call("delete", {
config = config,
type = stype,
match = comparator
})
elseif type(comparator) == "function" then
- local rv = util.ubus("uci", "get", {
+ local rv = call("get", {
config = config,
type = stype
})
@@ -389,7 +407,7 @@ function delete_all(self, config, stype, comparator)
local sname, section
for sname, section in pairs(rv.values) do
if comparator(section) then
- _, err = util.ubus("uci", "delete", {
+ _, err = call("delete", {
config = config,
section = sname
})
@@ -397,7 +415,7 @@ function delete_all(self, config, stype, comparator)
end
end
elseif comparator == nil then
- _, err = util.ubus("uci", "delete", {
+ _, err = call("delete", {
config = config,
type = stype
})
diff --git a/modules/luci-base/luasrc/model/uci.luadoc b/modules/luci-base/luasrc/model/uci.luadoc
index 49093c793..ef89d09b9 100644
--- a/modules/luci-base/luasrc/model/uci.luadoc
+++ b/modules/luci-base/luasrc/model/uci.luadoc
@@ -14,224 +14,226 @@ module "luci.model.uci"
---[[
Create a new UCI-Cursor.
-@class function
-@name cursor
-@return UCI-Cursor
+@class function
+@name cursor
+@return UCI-Cursor
]]
---[[
Create a new Cursor initialized to the state directory.
-@class function
-@name cursor_state
-@return UCI cursor
+@class function
+@name cursor_state
+@return UCI cursor
]]
---[[
Applies UCI configuration changes
-@class function
-@name Cursor.apply
-@param configlist List of UCI configurations
-@param command Don't apply only return the command
+@class function
+@name Cursor.apply
+@param configlist List of UCI configurations
+@param command Don't apply only return the command
]]
---[[
Delete all sections of a given type that match certain criteria.
-@class function
-@name Cursor.delete_all
+@class function
+@name Cursor.delete_all
@param config UCI config
@param type UCI section type
-@param comparator Function that will be called for each section and
-returns a boolean whether to delete the current section (optional)
+@param comparator Function that will be called for each section and returns
+ a boolean whether to delete the current section (optional)
]]
---[[
Create a new section and initialize it with data.
-@class function
-@name Cursor.section
-@param config UCI config
-@param type UCI section type
-@param name UCI section name (optional)
-@param values Table of key - value pairs to initialize the section with
-@return Name of created section
+@class function
+@name Cursor.section
+@param config UCI config
+@param type UCI section type
+@param name UCI section name (optional)
+@param values Table of key - value pairs to initialize the section with
+@return Name of created section
]]
---[[
Updated the data of a section using data from a table.
-@class function
-@name Cursor.tset
-@param config UCI config
-@param section UCI section name (optional)
-@param values Table of key - value pairs to update the section with
+@class function
+@name Cursor.tset
+@param config UCI config
+@param section UCI section name (optional)
+@param values Table of key - value pairs to update the section with
]]
---[[
Get a boolean option and return it's value as true or false.
-@class function
-@name Cursor.get_bool
-@param config UCI config
-@param section UCI section name
-@param option UCI option
-@return Boolean
+@class function
+@name Cursor.get_bool
+@param config UCI config
+@param section UCI section name
+@param option UCI option
+@return Boolean
]]
---[[
Get an option or list and return values as table.
-@class function
-@name Cursor.get_list
-@param config UCI config
-@param section UCI section name
-@param option UCI option
-@return table. If the option was not found, you will simply get
--- an empty table.
+@class function
+@name Cursor.get_list
+@param config UCI config
+@param section UCI section name
+@param option UCI option
+@return table. If the option was not found, you will simply get an empty
+ table.
]]
---[[
Get the given option from the first section with the given type.
-@class function
-@name Cursor.get_first
-@param config UCI config
-@param type UCI section type
-@param option UCI option (optional)
-@param default Default value (optional)
-@return UCI value
+@class function
+@name Cursor.get_first
+@param config UCI config
+@param type UCI section type
+@param option UCI option (optional)
+@param default Default value (optional)
+@return UCI value
]]
---[[
Set given values as list. Setting a list option to an empty list
has the same effect as deleting the option.
-@class function
-@name Cursor.set_list
-@param config UCI config
-@param section UCI section name
-@param option UCI option
-@param value value or table. Raw values will become a single item table.
-@return Boolean whether operation succeeded
+@class function
+@name Cursor.set_list
+@param config UCI config
+@param section UCI section name
+@param option UCI option
+@param value Value or table. Non-table values will be set as single
+ item UCI list.
+@return Boolean whether operation succeeded
]]
---[[
-Create a sub-state of this cursor. The sub-state is tied to the parent
+Create a sub-state of this cursor.
-curser, means it the parent unloads or loads configs, the sub state will
-do so as well.
-@class function
-@name Cursor.substate
-@return UCI state cursor tied to the parent cursor
+The sub-state is tied to the parent curser, means it the parent unloads or
+loads configs, the sub state will do so as well.
+
+@class function
+@name Cursor.substate
+@return UCI state cursor tied to the parent cursor
]]
---[[
Add an anonymous section.
-@class function
-@name Cursor.add
-@param config UCI config
-@param type UCI section type
-@return Name of created section
+@class function
+@name Cursor.add
+@param config UCI config
+@param type UCI section type
+@return Name of created section
]]
---[[
Get a table of saved but uncommitted changes.
-@class function
-@name Cursor.changes
-@param config UCI config
-@return Table of changes
-@see Cursor.save
+@class function
+@name Cursor.changes
+@param config UCI config
+@return Table of changes
+@see Cursor.save
]]
---[[
Commit saved changes.
-@class function
-@name Cursor.commit
-@param config UCI config
-@return Boolean whether operation succeeded
-@see Cursor.revert
-@see Cursor.save
+@class function
+@name Cursor.commit
+@param config UCI config
+@return Boolean whether operation succeeded
+@see Cursor.revert
+@see Cursor.save
]]
---[[
Deletes a section or an option.
-@class function
-@name Cursor.delete
-@param config UCI config
-@param section UCI section name
-@param option UCI option (optional)
-@return Boolean whether operation succeeded
+@class function
+@name Cursor.delete
+@param config UCI config
+@param section UCI section name
+@param option UCI option (optional)
+@return Boolean whether operation succeeded
]]
---[[
Call a function for every section of a certain type.
-@class function
-@name Cursor.foreach
-@param config UCI config
-@param type UCI section type
-@param callback Function to be called
-@return Boolean whether operation succeeded
+@class function
+@name Cursor.foreach
+@param config UCI config
+@param type UCI section type
+@param callback Function to be called
+@return Boolean whether operation succeeded
]]
---[[
Get a section type or an option
-@class function
-@name Cursor.get
-@param config UCI config
-@param section UCI section name
-@param option UCI option (optional)
-@return UCI value
+@class function
+@name Cursor.get
+@param config UCI config
+@param section UCI section name
+@param option UCI option (optional)
+@return UCI value
]]
---[[
Get all sections of a config or all values of a section.
-@class function
-@name Cursor.get_all
-@param config UCI config
-@param section UCI section name (optional)
-@return Table of UCI sections or table of UCI values
+@class function
+@name Cursor.get_all
+@param config UCI config
+@param section UCI section name (optional)
+@return Table of UCI sections or table of UCI values
]]
---[[
Manually load a config.
-@class function
-@name Cursor.load
-@param config UCI config
-@return Boolean whether operation succeeded
-@see Cursor.save
-@see Cursor.unload
+@class function
+@name Cursor.load
+@param config UCI config
+@return Boolean whether operation succeeded
+@see Cursor.save
+@see Cursor.unload
]]
---[[
Revert saved but uncommitted changes.
-@class function
-@name Cursor.revert
-@param config UCI config
-@return Boolean whether operation succeeded
-@see Cursor.commit
-@see Cursor.save
+@class function
+@name Cursor.revert
+@param config UCI config
+@return Boolean whether operation succeeded
+@see Cursor.commit
+@see Cursor.save
]]
---[[
Saves changes made to a config to make them committable.
-@class function
-@name Cursor.save
-@param config UCI config
-@return Boolean whether operation succeeded
-@see Cursor.load
-@see Cursor.unload
+@class function
+@name Cursor.save
+@param config UCI config
+@return Boolean whether operation succeeded
+@see Cursor.load
+@see Cursor.unload
]]
---[[
@@ -243,57 +245,74 @@ then a named section of the given type is created.
When invoked with four arguments `config`, `sectionname`, `optionname` and
`optionvalue` then the value of the specified option is set to the given value.
-@class function
-@name Cursor.set
-@param config UCI config
-@param section UCI section name
-@param option UCI option or UCI section type
+@class function
+@name Cursor.set
+@param config UCI config
+@param section UCI section name
+@param option UCI option or UCI section type
@param value UCI value or nothing if you want to create a section
-@return Boolean whether operation succeeded
+@return Boolean whether operation succeeded
]]
---[[
Get the configuration directory.
-@class function
-@name Cursor.get_confdir
-@return Configuration directory
+@class function
+@name Cursor.get_confdir
+@return Configuration directory
]]
---[[
Get the directory for uncomitted changes.
-@class function
-@name Cursor.get_savedir
-@return Save directory
+@class function
+@name Cursor.get_savedir
+@return Save directory
+]]
+
+---[[
+Get the effective session ID.
+
+@class function
+@name Cursor.get_session_id
+@return String containing the session ID
]]
---[[
Set the configuration directory.
-@class function
-@name Cursor.set_confdir
+@class function
+@name Cursor.set_confdir
@param directory UCI configuration directory
-@return Boolean whether operation succeeded
+@return Boolean whether operation succeeded
]]
---[[
Set the directory for uncommited changes.
-@class function
-@name Cursor.set_savedir
+@class function
+@name Cursor.set_savedir
@param directory UCI changes directory
-@return Boolean whether operation succeeded
+@return Boolean whether operation succeeded
+]]
+
+---[[
+Set the effective session ID.
+
+@class function
+@name Cursor.set_session_id
+@param id String containing the session ID to set
+@return Boolean whether operation succeeded
]]
---[[
Discard changes made to a config.
-@class function
-@name Cursor.unload
-@param config UCI config
-@return Boolean whether operation succeeded
-@see Cursor.load
-@see Cursor.save
+@class function
+@name Cursor.unload
+@param config UCI config
+@return Boolean whether operation succeeded
+@see Cursor.load
+@see Cursor.save
]]