123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- -- ===================================================================
- -- /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, 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, type)
- local entry = modpol.create_ledger_entry(msg,org_name,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 org_ledger == nil then
- modpol.orgs [org_name]["ledger"] = { entry }
- else
- modpol.orgs [org_name]["ledger"] =
- table.insert (org_ledger, entry)
- end
- end
- modpol.store_data() -- Copy data to disk
- end
- -- ===================================================================
- -- Function: modpol.add_org
- -- Params: string name, table members, string parent, table properties
- -- Output:
- --
- -- 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 members table should be an integer-indexed array of member
- -- names.
- -- 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 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 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
- local msg = "New org: " .. org_name ..
- " (" .. table.concat (members, ", ") .. ")"
- 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
- -- Output:
- -- This function returns a text-format list of "orgs". The list shows
- -- one "org" per line in the following format:
- -- org_name (member, member, ...)
- -- If there are no "orgs", the output is an empty string.
- modpol.list_orgs = function()
- local outbuf = ""
- local str
- for org_name, org_data in pairs (modpol.orgs) do
- -- Process next "org"
- -- Build string version of member list
- local memcat = org_data ["members"]
- if modpol.ocutil.str_empty (memcat) then
- memcat = "(empty)"
- else
- memcat = "(" .. table.concat (memcat, ", ") .. ")"
- end
- -- Build output string
- outbuf = outbuf .. org_name .. " " .. memcat .. "\n"
- end
- return outbuf
- end
- -- ===================================================================
- -- Function: modpol.reset_orgs
- -- Params: None
- -- Removes all orgs and recreates blank org "instance" with all
- -- current users
- -- returns confirmation message
- 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, 'org_purge')
- modpol.add_org("instance", users)
- return message
- end
- -- ===================================================================
- -- Function: modpol.add_member
- -- Params: org (string), member (string)
- -- Output:
- -- Adds the specified member to the specified org
- -- Returns a boolean success indicator and
- -- either a confirmation or error message
- -- 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_name,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')
- return true,message
- end
- end
- end
- -- ===================================================================
- -- Function: modpol.is_member
- -- Params: org (string), member (string)
- -- Output: Boolean depending on membership or nil/error message
- modpol.is_member = function(org, member)
- if (modpol.orgs[org] == nil) then
- return nil, "Error: No such org"
- 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
- return true
- end
- end
- -- no match found
- return false
- end
- return false
- end
- end
- -- ===================================================================
- -- Function: modpol.remove_member
- -- Params: org (string), member (string)
- -- Output:
- -- Removes the specified member from the specified org
- -- Returns confirmation or error message
- function modpol.remove_member(org, member)
- local message = "Error: No such org"
- if (modpol.orgs[org] == nil) then
- 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
-
- modpol.orgs[org]["members"][value] = nil
-
- -- TODO: add callbacks here --
- message = member .. " removed from org " .. org
- 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 false, message
- end
- end
- -- ===================================================================
- -- TKTK
- -- rename_org(old_name, new_name)
- -- Renames an org
-
- -- ===================================================================
- -- POLICIES
- -- Each policy is a table with a string for a key. Contents:
- -- KEY - name of the policy (string)
- -- [member orgs]: external orgs allowed to call policy
- -- [function]: the function that initiates the policy
- -- ===================================================================
- -- ===================================================================
- -- modpol.add_policy
- -- Adds a policy to an org's [org].policies table
- -- Params: org_name (string),
- -- policy_name (string),
- -- policy_table (table)
- -- Output: true if successful, nil if error
- -- TKTK NEEDS TO BE REWRITTEN
- modpol.add_policy = function(org_name, policy_name, policy_table)
- -- first, basic checks
- local message = "Error: No such org"
- if (modpol.orgs[org_name] == nil) then
- return nil, message
- elseif (modpol[target_function] == nil) then
- message = "Error: No such target function"
- return nil, message
- elseif (modpol[policy_function]) then
- message = "Error: No such policy function"
- return nil, message
- else
- -- okay, proceed
- modpol.orgs[org_name].policies[target_function] = policy_function
- message = "In org " .. org_name .. ", policy for " .. target_function
- .. " set to " .. policy_function
- record(org_name, message)
- return true, message
- end
- end
- -- ===================================================================
- -- End of file.
|