rework orgs. Add various properties to orgs. Make all org functions return success boolean as well as error/success string message.

This commit is contained in:
MisterE123
2021-03-01 19:11:20 -05:00
parent 4f53e801c4
commit d646a4a8dd
4 changed files with 414 additions and 33 deletions

View File

@@ -1,30 +1,94 @@
-- ===================================================================
-- /orgs.lua
-- Org-related functions for Modular Politics
-- Called by modpol/modpol/api.lua
-- ===================================================================
-- preserve records -- if true, will store org ledgers when they are closed, for later reference.
local preserve_records = true
modpol.default_org_policies = modpol.default_org_policies or {}
-- initiate the table of orgs
modpol.orgs = {}
if preserve_records then
modpol.old_ledgers = {} -- a backup of all legders of all closed orgs.
end
--define the template of a ledger entry
modpol.ledger_entry_temp = {
timestamp = '',
entrytype = nil,
action_msg = '',
org_name = nil,
}
-- define the basic template of an org.
modpol.org_temp = {
name = nil,
policies = {},
members = {},
ledger = {},
parent = nil,
children = {},
properties = {},
old_names = {},
}
-- ===================================================================
-- Function: modpol.create_ledger_entry
-- Params: strings action_msg, org_name, type
-- Outputs:
-- returns a ledger entry table, with a timestamp
-- This function accepts a message and an optional org_name and type specification
-- and returns a valid ledger entry table
modpol.create_ledger_entry = function(action_msg, org_name, 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
end
if entry_type and type(entry_type) == 'string' then
entry.entrytype = entry_type
end
entry.timestamp = os.time()
return entry
end
-- ===================================================================
-- Function: modpol.record
-- Params: strings msg, org
-- Params: strings msg, org, type
-- Outputs:
-- "msg" specifies an event and/or status message.
-- "org" specifies an "org" name.
-- "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)
modpol.record = function (org_name, msg, type)
local entry = modpol.create_ledger_entry(msg,org_name,type)
-- Record in global ledger
table.insert (modpol.ledger, msg)
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 org_ledger == nil then
modpol.orgs [org_name]["ledger"] = { msg }
modpol.orgs [org_name]["ledger"] = { entry }
else
modpol.orgs [org_name]["ledger"] =
table.insert (org_ledger, msg)
table.insert (org_ledger, entry)
end
end
@@ -33,39 +97,144 @@ end
-- ===================================================================
-- Function: modpol.add_org
-- Params: string name, table members
-- Params: string name, table members, string parent, table properties
-- Output:
--
-- This function creates an "org". It returns either an error message
-- starting with "-!-" or a success message.
-- This function creates an "org". It returns a boolean success indicator and
-- either an error message starting with "Error:" or a success message.
--
-- The string parameter specifies the "org" name.
--
-- The specified table should be an integer-indexed array of member
-- The members table should be an integer-indexed array of member
-- names.
modpol.add_org = function (org_name, members)
-- parent should be nil or a valid existing org name. If nil, defaults to
-- 'instance'
-- properties defaults to an empty table. Use it to initialize the org
-- with arbitrary properties
modpol.add_org = function(org_name, members, parent, properties)
local str
if modpol.ocutil.str_empty (org_name) then
return "Error: Org needs a name"
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"
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
str = "Error: Org " .. org_name .. " already exists"
modpol.ocutil.log (str)
return str
return false,str
end
local parent_org = parent or 'instance'
local props = properties or {}
-- 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
--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}
end
modpol.orgs [org_name] = { members=members }
local msg = "New org: " .. org_name ..
" (" .. table.concat (members, ", ") .. ")"
modpol.record (org_name, msg)
return msg
modpol.record (org_name, msg, 'org_init')
return true, msg
end
-- ===================================================================
-- Function: modpol.remove_org
-- Params: string name, opt string reason
-- Output:
--
-- This function removes an "org". It returns a boolean
-- success indicator and either an error message
-- 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
-- The string parameter specifies the "org" name.
--
-- The reason is an optional string to additionally include in the
-- log as reason for removal
modpol.remove_org = function (org_name, 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"
end
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
-- 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
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
end
end
modpol.orgs[org_name] = nil
return true,msg
end
-- ===================================================================
-- Function: modpol.list_orgs
-- Params: None
@@ -102,9 +271,17 @@ end
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
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)
end
end
modpol.orgs = {}
local message = "Orgs purged"
modpol.record(nil, message)
modpol.record(nil, message, 'org_purge')
modpol.add_org("instance", users)
return message
end
@@ -114,19 +291,25 @@ end
-- Params: org (string), member (string)
-- Output:
-- Adds the specified member to the specified org
-- Returns confirmation or error message
-- Returns a boolean success indicator and
-- either a confirmation or error message
modpol.add_member = function(org, member)
if (modpol.orgs[org] == nil) then
return "Error: No such org"
-- 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
return false,"Error: No such org"
elseif type(member) ~= 'string' then
return false,"Error: member is wrong type"
else
if modpol.is_member(org,member) then
return "Error: " .. member .. " is already a member of " .. org
if modpol.is_member(org_name,member) then
return false,"Error: " .. member .. " is already a member of " .. org_name
else
table.insert(modpol.orgs[org]["members"], member)
local message = member .. " added to org " .. org
modpol.record(message, org)
return message
table.insert(modpol.orgs[org_name]["members"], member)
local message = member .. " added to org " .. org_name
modpol.record(org_name, message, 'add_member')
return true,message
end
end
end
@@ -165,22 +348,26 @@ end
function modpol.remove_member(org, member)
local message = "Error: No such org"
if (modpol.orgs[org] == nil) then
return nil, message
return false, message
else
local member_table = modpol.orgs[org]["members"]
if member_table then
for index, value in pairs(member_table) do
if value == member then
-- match found, set to nil
value = nil
modpol.orgs[org]["members"][value] = nil
-- TODO: add callbacks here --
message = member .. " removed from org " .. org
return message
modpol.record(org_name, message, 'remove_member')
return true, message
end
end
end
-- no match found (or org has no members)
message = member .. " not found in org " .. org
return nil, message
return false, message
end
end
@@ -189,6 +376,13 @@ end
-- rename_org(old_name, new_name)
-- Renames an org
-- ===================================================================
-- POLICIES
-- Each policy is a table with a string for a key. Contents: