change orgs to use id numbers as their table key and function input param

This commit is contained in:
MisterE123 2021-03-08 14:06:15 -05:00
parent 418926f551
commit 419fc84822
5 changed files with 228 additions and 93 deletions

View File

@ -4,7 +4,7 @@ they are *not* just a message in a table anymore... they have a timestamp and mo
===============
Orgs are stored in modpol.orgs by the key 'org_name'
Orgs are stored in modpol.orgs by the key 'org_id', a unique integer
Old ledgers of deleted orgs are stored in modpol.old_ledgers,
if preserve records is enabled
@ -36,8 +36,8 @@ to store old ledgers when an org is deleted. It is set to true.
It would be possible to extend this to a settings file later.
--==oo888888888888888888888888888888oo==--
Function: modpol.record(org_name, msg, type)
-- Params: strings msg, org, type
Function: modpol.record(org_id, msg, type)
-- Params: strings msg, type, org_id (number)
-- Outputs:
-- "msg" specifies an event and/or status message.
-- "org" specifies an "org" name.
@ -52,8 +52,8 @@ Function: modpol.record(org_name, msg, type)
--==oo888888888888888888888888888888oo==--
Function: modpol.add_org(org_name, members, parent, properties)
-- Params: string name, table members, string parent, table properties
Function: modpol.add_org(org_id, members, parent, properties)
-- Params: org)id (number), table members, string parent, table properties
-- Parent must be an existing org, defaults to 'instance', properties
-- are arbitrary properties to initialize the org with
@ -75,8 +75,8 @@ Function: modpol.add_org(org_name, members, parent, properties)
--==oo888888888888888888888888888888oo==--
-- Function: modpol.remove_org(org_name, reason)
-- Params: string name, opt string reason
-- Function: modpol.remove_org(org_id, reason)
-- Params: org_id (number), opt string reason
-- Output:
--
-- This function removes an "org". It returns a boolean
@ -114,8 +114,8 @@ Function: modpol.reset_orgs()
--==oo888888888888888888888888888888oo==--
Function: modpol.add_member(org_name, member)
-- Params: org_name (string), member (string)
Function: modpol.add_member(org_id, member)
-- Params: org_id (number), member (string)
-- Output:
-- Adds the specified member to the specified org
-- Returns a boolean success indicator and
@ -124,14 +124,14 @@ Function: modpol.add_member(org_name, member)
--==oo888888888888888888888888888888oo==--
Function: modpol.is_member
-- Params: org (string), member (string)
-- Params: org (number), member (string)
-- Output: boolean, or nil and error message if not applicable. (org nonexistent)
--==oo888888888888888888888888888888oo==--
Function: modpol.remove_member
-- Params: org (string), member (string)
-- Params: org (number), member (string)
-- Output:
-- Removes the specified member from the specified org
-- Returns confirmation or error message

View File

@ -6,29 +6,58 @@
-- ===================================================================
-- preserve records -- if true, will store org ledgers when they are closed, for later reference.
local preserve_records = true
-- policies assigned to any org can go here
modpol.default_org_policies = modpol.default_org_policies or {}
-- initiate the table of orgs
modpol.orgs = {}
-- initiate the table of orgs, if it doesnt already exist from storage!
modpol.orgs = modpol.orgs or {}
if preserve_records then
modpol.old_ledgers = {} -- a backup of all legders of all closed orgs.
modpol.old_ledgers = modpol.old_ledgers or {} -- a backup of all legders of all closed orgs.
end
-- this counter will increment every time a new org is created, and the current value will be used as the org id
-- we set it to 1 for init, and then run through all existing orgs and take only the greatest... which we then add 1 to.
-- this ensures a unique id for each org.
modpol.id_counter = 1
if #modpol.orgs > 0 then
for id,org in pairs(modpol.orgs) do
if id > modpol.id_counter then
modpol.id_counter = id
end
end
for id,ledg in pairs(modpol.old_ledgers) do
if id > modpol.id_counter then
modpol.id_counter = id
end
end
modpol.id_counter = modpol.id_counter +1
end
--define the template of a ledger entry
modpol.ledger_entry_temp = {
timestamp = '',
entrytype = nil,
action_msg = '',
org_name = nil,
org_id = nil,
}
-- define the basic template of an org.
modpol.org_temp = {
id = nil,
name = nil,
policies = {},
members = {},
@ -42,19 +71,22 @@ modpol.org_temp = {
-- ===================================================================
-- Function: modpol.create_ledger_entry
-- Params: strings action_msg, org_name, type
-- Params: strings: action_msg, type, number: org_id
-- Outputs:
-- returns a ledger entry table, with a timestamp
-- This function accepts a message and an optional org_name and type specification
-- This function accepts a message and an optional org_id and type specification
-- and returns a valid ledger entry table
modpol.create_ledger_entry = function(action_msg, org_name, entry_type)
modpol.create_ledger_entry = function(action_msg, org_id, entry_type)
local entry = modpol.ledger_entry_temp
if action_msg and type(action_msg) == 'string' then
entry.action_msg = action_msg
end
if org_name and type(org_name) == 'string' and modpol.orgs [org_name] then
entry.org_name = org_name
if org_id and type(org_id) == 'number' and modpol.orgs [org_id] then
entry.org_id = org_id
if modpol.orgs[org_id].name then
entry.org_name = modpol.orgs[org_id].name
end
end
if entry_type and type(entry_type) == 'string' then
entry.entrytype = entry_type
@ -66,35 +98,54 @@ end
-- ===================================================================
-- Function: modpol.record
-- Params: strings msg, org, type
-- Params: strings msg, type, number org_id
-- Outputs:
-- "msg" specifies an event and/or status message.
-- "org" specifies an "org" name.
-- "org" specifies an "org" id.
-- "type" -- optional type of legder entry. Could be e.g. 'election_result', 'add_member', etc
-- This function adds the message to a global ledger and, if "org"
-- specifies a valid "org", to an "org"-specific ledger. Both the mem-
-- ory-resident and on-disk copies of the data structures used are up-
-- dated.
modpol.record = function (org_name, msg, type)
modpol.record = function (org_id, msg, type)
local entry = modpol.create_ledger_entry(msg,org_name,type)
local entry = modpol.create_ledger_entry(msg, org_id, type)
-- Record in global ledger
table.insert (modpol.ledger, entry)
-- Record in "org"-specific ledger
if modpol.orgs [org_name] ~= nil then
local org_ledger = modpol.orgs [org_name]["ledger"]
if modpol.orgs [org_id] ~= nil then
local org_ledger = modpol.orgs [org_id]["ledger"]
if org_ledger == nil then
modpol.orgs [org_name]["ledger"] = { entry }
modpol.orgs [org_id]["ledger"] = { entry }
else
modpol.orgs [org_name]["ledger"] =
table.insert (org_ledger, entry)
modpol.orgs [org_id]["ledger"] = table.insert (org_ledger, entry)
end
end
modpol.store_data() -- Copy data to disk
end
-- ===================================================================
-- Function: modpol.get_org_id_by_name(org_name)
-- Params: org_name
-- Output: an org id or nil
--
modpol.get_org_id_by_name = function(org_name)
local id = nil
for org_id,org in pairs(modpol.orgs) do
if org.name == org_name then
id = org_id
end
end
return id
end
-- ===================================================================
-- Function: modpol.add_org
-- Params: string name, table members, string parent, table properties
@ -115,54 +166,78 @@ end
-- properties defaults to an empty table. Use it to initialize the org
-- with arbitrary properties
modpol.add_org = function(org_name, members, parent, properties)
modpol.add_org = function(org_name, members, parent_id, properties)
local str
if modpol.ocutil.str_empty (org_name) then
return false,"Error: Org needs a name"
end
if parent and not modpol.orgs[parent] then
return false,"Error: Parent must be a valid org"
if parent_id and not modpol.orgs[parent_id] then
return false,"Error: Parent_id must be a valid existing org id"
end
if properties and not type(properties) == 'table' then
return false,"Error: Properties must be a table"
end
modpol.ocutil.log ("Adding org " .. org_name)
if modpol.orgs [org_name] ~= nil then
modpol.ocutil.log ("Attempting to add new org " .. org_name)
if modpol.get_org_id_by_name(org_name) ~= nil then
str = "Error: Org " .. org_name .. " already exists"
modpol.ocutil.log (str)
return false,str
end
local parent_org = parent or 'instance'
local props = properties or {}
local org_id = modpol.id_counter
modpol.id_counter = modpol.id_counter + 1
-- actually add the org
local org = modpol.org_temp
local default_policies = modpol.default_org_policies or {}
org.name = org_name -- do not change this without the proper api function. This is only a reference, not the only place this is recorded.
org.members = members
org.parent = parent_org
org.properties = props
org.policies = default_policies
modpol.orgs [org_name] = org
-- the instance will have a parent of nil if it is the instance.
-- otherwise, it will have a parent of instance's id if not otherwise defined
local parent_org_id = nil
--record the child org in the parent's children table
if modpol.orgs[parent_org].children then
table.insert(modpol.orgs[parent_org].children, org_name)
else
modpol.orgs[parent].children = {org_name}
if parent_id and not(modpol.get_org_id_by_name('instance') == org_id) then
parent_org_id = parent_id
end
local msg = "New org: " .. org_name ..
" (" .. table.concat (members, ", ") .. ")"
if not parent_id and not(modpol.get_org_id_by_name('instance') == org_id) then
parent_org_id = modpol.get_org_id_by_name('instance')
end
modpol.record (org_name, msg, 'org_init')
local props = properties or {}
-- actually add the org
local org = modpol.org_temp
local default_policies = modpol.default_org_policies or {}
org.id = org_id
org.name = org_name -- do not change this without the proper api function. This is only a reference, not the only place this is recorded.
org.members = members
org.parent = parent_org_id
org.properties = props
org.policies = default_policies
modpol.orgs [org_id] = org
--record the child org in the parent's children table
if parent_org_id then
if modpol.orgs[parent_org_id].children then
table.insert(modpol.orgs[parent_org_id].children, org_id)
else
modpol.orgs[parent_org_id].children = {org_id}
end
end
local msg = "New org: " .. org_name .. " ["..org_id.."], parent = ".. dump(parent_org_id)..", members = "..
" (" .. table.concat (members, ", ") .. ")"
modpol.record (org_id, msg, 'org_init')
return true, msg
end
@ -171,7 +246,7 @@ end
-- ===================================================================
-- Function: modpol.remove_org
-- Params: string name, opt string reason
-- Params: number id, opt string reason
-- Output:
--
-- This function removes an "org". It returns a boolean
@ -179,51 +254,58 @@ end
-- starting with "Error:" or a success message. It also recursively
-- removes all child orgs, with 'remove parent org' as reason. If
-- preserve_records is enabled, it logs the removal in the org ledger,
-- and stores the ledger in modpol.old_legders
-- and stores the ledger in modpol.old_ledgers
-- The string parameter specifies the "org" name.
-- The number parameter specifies the "org" id.
--
-- The reason is an optional string to additionally include in the
-- log as reason for removal
modpol.remove_org = function (org_name, reason)
modpol.remove_org = function (org_id, reason)
local str
if not reason then reason = '' end
if modpol.ocutil.str_empty (org_name) then
return false,"Error: Specify an org name to remove"
if not type(org_id) == 'number' or not modpol.orgs[org_id] then
str = "Error: Specify an existing org id to remove"
modpol.ocutil.log (str)
return false,str
end
local org_name = modpol.orgs[org_id]
if org_name == 'instance' then
return false,"Error: You cannot remove instance"
end
modpol.ocutil.log ("Removing org " .. org_name)
if modpol.orgs [org_name] == nil then
str = "Error: Cannot remove non-existant org " .. org_name
modpol.ocutil.log (str)
return false,str
end
--log msg
local msg = 'Removing org '..org_name ..', reason: '.. reason
local msg = 'Removing org '..org_name ..' ['..org_id..'], reason: '.. reason
modpol.ocutil.log (msg)
-- actually remove the org
modpol.record (org_name, msg, 'org_remove')
-- TODO: if callbacks are implemented, do so here --
if preserve_records then
modpol.old_ledgers = modpol.orgs[org_name].ledger
modpol.old_ledgers[org_id] = modpol.orgs[org_id].ledger
end
-- also remove all children
if modpol.orgs[org_name].children and #modpol.orgs[org_name].children > 0 then
for _,child_name in pairs(modpol.orgs[org_name].children) do
modpol.remove_org(child_name, 'remove parent org') --this is recursion. If it gets to be a problem, we will need a separate function
if modpol.orgs[org_id].children and #modpol.orgs[org_id].children > 0 then
for _,child_name in pairs(modpol.orgs[org_id].children) do
--this is recursion. If it gets to be a problem, we will need a separate function
modpol.remove_org(child_name, 'remove parent org')
end
end
modpol.orgs[org_name] = nil
--also remove references to this org in parent orgs
if modpol.orgs[org_id].parent then
local parent_id = modpol.orgs[org_id].parent
modpol.orgs[parent_id].children[org_id] = nil
end
modpol.orgs[org_id] = nil
modpol.record (org_id, msg, 'org_remove')
return true,msg
@ -247,10 +329,11 @@ end
modpol.list_orgs = function()
local outbuf = ""
local str
for org_name, org_data in pairs (modpol.orgs) do
for org_id, org_data in pairs (modpol.orgs) do
-- Process next "org"
-- Build string version of member list
local memcat = org_data ["members"]
local org_name = org_data ["name"].."["..org_id.."]"
if modpol.ocutil.str_empty (memcat) then
memcat = "(empty)"
else
@ -273,10 +356,10 @@ modpol.reset_orgs = function()
local users = modpol.list_users()
--store the ledgers in modpol.old_ledgers, and note that each org was closed in each record.
if preserve_records then
for name, org in pairs(modpol.orgs) do
for id, org in pairs(modpol.orgs) do
local old_ledger = org.ledger
table.insert(old_ledger,modpol.create_ledger_entry('Removing org '.. name, name, 'org_purge'))
table.insert(modpol.old_ledgers, org.ledger)
table.insert(old_ledger,modpol.create_ledger_entry('Removing org '.. id, id, 'org_purge'))
modpol.old_ledgers[id] = old_ledger
end
end
modpol.orgs = {}
@ -288,7 +371,7 @@ end
-- ===================================================================
-- Function: modpol.add_member
-- Params: org (string), member (string)
-- Params: org_id (number), member (string)
-- Output:
-- Adds the specified member to the specified org
-- Returns a boolean success indicator and
@ -297,18 +380,20 @@ end
-- TODO, check that member is a user, if the org_name is not instance
modpol.add_member = function(org_name, member)
if (modpol.orgs[org_name] == nil) then
modpol.add_member = function(org_id, member)
if (modpol.orgs[org_id] == nil) then
return false,"Error: No such org"
elseif type(member) ~= 'string' then
return false,"Error: member is wrong type"
else
if modpol.is_member(org_name,member) then
local org_name = modpol.orgs [org_id].name
if modpol.is_member(org_id,member) then
return false,"Error: " .. member .. " is already a member of " .. org_name
else
table.insert(modpol.orgs[org_name]["members"], member)
local message = member .. " added to org " .. org_name
modpol.record(org_name, message, 'add_member')
table.insert(modpol.orgs[org_id]["members"], member)
local message = member .. " added to org " .. org_name .. " ["..org_id.."]"
modpol.record(org_id, message, 'add_member')
return true,message
end
end
@ -316,7 +401,7 @@ end
-- ===================================================================
-- Function: modpol.is_member
-- Params: org (string), member (string)
-- Params: org (number), member (string)
-- Output: Boolean depending on membership or nil/error message
modpol.is_member = function(org, member)
@ -340,7 +425,7 @@ end
-- ===================================================================
-- Function: modpol.remove_member
-- Params: org (string), member (string)
-- Params: org (number), member (string)
-- Output:
-- Removes the specified member from the specified org
-- Returns confirmation or error message
@ -358,9 +443,10 @@ function modpol.remove_member(org, member)
modpol.orgs[org]["members"][value] = nil
-- TODO: add callbacks here --
-- TODO: add callbacks here, for such as revoking privs, etc --
message = member .. " removed from org " .. org
modpol.record(org_name, message, 'remove_member')
modpol.record(org, message, 'remove_member')
return true, message
end
end

View File

@ -9,6 +9,7 @@
modpol.datadir = modpol.topdir .. "/data"
modpol.file_ledger = modpol.datadir .. "/ledger.dat"
modpol.file_orgs = modpol.datadir .. "/orgs.dat"
modpol.file_old_ledgers = modpol.datadir .. "/old_ledgers.dat"
os.execute ("mkdir -p " .. modpol.datadir)
@ -43,8 +44,7 @@ end
local store_orgs = function()
local ok = modpol.ocutil.file_write (modpol.file_orgs,
modpol.serpent.dump (modpol.orgs))
modpol.serpent.dump (modpol.orgs))
if ok ~= true then
modpol.ocutil.fatal_error ("store_data: orgs")
end
@ -55,12 +55,32 @@ modpol.serpent.dump (modpol.orgs))
modpol.ocutil.log (nn .. " orgs stored to disk")
end
-- ===================================================================
-- This function stores "old_ledgers" data to disk.
local store_old_ledgers = function()
local ok = modpol.ocutil.file_write (modpol.file_old_ledgers,
modpol.serpent.dump (modpol.old_ledgers))
if ok ~= true then
modpol.ocutil.fatal_error ("store_data: orgs")
end
local nn = modpol.ocutil.table_length (modpol.old_ledgers)
local str = "entries"
if nn == 1 then str = "entry" end
modpol.ocutil.log (nn .. " orgs stored to disk")
end
-- ===================================================================
-- This function stores data to disk.
modpol.store_data = function()
store_ledger()
store_orgs()
store_old_ledgers()
end
-- ===================================================================
@ -105,12 +125,34 @@ local load_orgs = function()
end
end
-- ===================================================================
-- This function loads "old_ledgers" data from disk.
local load_old_ledgers = function()
local obj = modpol.ocutil.file_read (modpol.file_old_ledgers )
if obj ~= nil then
local func, err = load (obj)
if err then
modpol.ocutil.fatal_error ("load_data: orgs" )
end
modpol.orgs = func()
local nn = modpol.ocutil.table_length (modpol.file_old_ledgers)
local str = "entries"
if nn == 1 then str = "entry" end
modpol.ocutil.log (nn .. " orgs loaded from disk")
else
modpol.ocutil.log ("No stored old ledgers data found")
end
end
-- ===================================================================
-- This function loads stored data from disk.
modpol.load_storage = function()
load_ledger()
load_orgs()
load_old_ledgers()
end
-- ===================================================================

View File

@ -59,7 +59,8 @@ minetest.register_chatcommand(
"joinorg", {
privs = {},
func = function(user, param)
local success, result = modpol.add_member(param, user)
local org_id = modpol.get_org_id_by_name(param)
local success, result = modpol.add_member(org_id, user)
return true, result
end,
})

View File

@ -18,11 +18,16 @@ modpol.load_storage = function()
if (stored_orgs ~= nil) then
modpol.orgs = stored_orgs
end
-- load orgs
-- load ledger
local stored_ledger = minetest.deserialize(mod_storage:get_string("ledger"))
if (stored_ledger ~= nil) then
modpol.ledger = stored_ledger
end
-- load old_ledgers
local old_stored_ledgers = minetest.deserialize(mod_storage:get_string("old_ledgers"))
if (stored_ledger ~= nil) then
modpol.old_ledgers = old_stored_ledgers
end
end
-- Stores content of current orgs and ledger to mod_storage
@ -31,4 +36,5 @@ modpol.store_data = function()
-- write to storage
mod_storage:set_string("orgs", minetest.serialize(modpol.orgs))
mod_storage:set_string("ledger", minetest.serialize(modpol.ledger))
mod_storage:set_string("old_ledgers", minetest.serialize(modpol.old_ledgers))
end