modpol/modpol/orgs/orgs.lua
2021-04-26 01:06:44 -04:00

372 lines
9.8 KiB
Lua

modpol.orgs = modpol.orgs or
{
count = 1,
array = {}
}
-- sets modpol.orgs as its own fallback
modpol.orgs.__index = modpol.orgs
function temp_org()
return {
id = nil,
name = nil,
policies = {},
processes = {},
requests = {},
request_count = 0,
members = {},
parent = nil,
children = {}
}
end
modpol.orgs.request_params = {
add_org = 1,
delete = 0,
add_member = 1,
remove_member = 1
}
-- ==================================================
-- returns org when given its id or name
function modpol.orgs.get_org(arg)
if type(arg) == 'string' then
for id, org in ipairs(modpol.orgs.array) do
if org.name == arg then
return org
end
end
elseif type(arg) == 'number' then
return modpol.orgs.array[arg]
end
return nil
end
-- ===============================================
-- returns a table list of all org names
function modpol.orgs.list_all()
local org_table
for k, v in ipairs(modpol.orgs.array) do
if type(v) == 'table' then
if org_table then
table.insert(org_table, v.name)
else
org_table = {v.name}
end
end
end
return org_table
end
-- Function: modpol.orgs.user_orgs(user)
-- input: user (string)
-- output: table of strings of org names
function modpol.orgs.user_orgs(user)
local all_orgs = modpol.orgs.list_all()
local user_orgs = {}
for i,v in ipairs(all_orgs) do
local this_table = modpol.orgs.get_org(v)
if this_table:has_member(user) then
table.insert(user_orgs,v)
end
end
return user_orgs
end
-- ===========================================
-- deletes all orgs except for the instance
function modpol.orgs.reset()
for id, org in ipairs(modpol.orgs.array) do
if id > 1 then
modpol.orgs.array[id] = nil
end
end
modpol.orgs:record('Resetting all orgs', 'org_reset')
end
-- ===================================================
-- initializes the instance (root org)
-- can only be run once, as only one instance can exist
function modpol.orgs.init_instance()
local error_msg
if modpol.orgs.array[1] then
modpol.ocutil.log('Error: instance has already been initialized')
return false
end
local instance = temp_org()
instance.id = 1
instance.name = "instance"
setmetatable(instance, modpol.orgs)
-- adding instance to org list
modpol.orgs.array[1] = instance
modpol.orgs:record('Initialized the instance org', 'create_instance')
return instance
end
-- FUNCTIONS BEYOND HERE OPERATE ON ORG OBJECTS
-- =======================================================
-- records a log message to the modpol ledger
function modpol.orgs:record(msg, entry_type)
local entry = {
timestamp = '',
entry_type = nil,
action_msg = '',
org_name = '',
org_id = nil,
}
if type(msg) == 'string' and not(modpol.ocutil.str_empty(msg)) then
entry.action_msg = msg
else
modpol.ocutil.log('Error: msg must be a non empty string')
return false
end
if type(entry_type) == 'string' and not(modpol.ocutil.str_empty(entry_type)) then
entry.entry_type = entry_type
else
modpol.ocutil.log('Error: entry_type must be a non empty string')
print(msg, entry_type)
return false
end
entry.timestamp = os.time()
entry.org_id = self.id
entry.org_name = self.name
table.insert(modpol.ledger, entry)
modpol.store_data()
end
-- ==================================================
-- adds a new sub org to the org it is called on
-- ex: instance:add_org('town hall')
function modpol.orgs:add_org(name)
if self.id == nil then
modpol.ocutil.log('Error: add_org can only be called by another org')
return false
end
if modpol.ocutil.str_empty(name) then
modpol.ocutil.log('Error: org name is required')
return false
end
if modpol.orgs.get_org(name) then
modpol.ocutil.log('Error: org name is already being used')
return false
end
-- creating the child sub org
modpol.orgs.count = modpol.orgs.count + 1
local child_org = temp_org()
child_org.id = modpol.orgs.count
child_org.name = name
child_org.parent = self.id
setmetatable(child_org, modpol.orgs)
-- adding child id to list of children
table.insert(self.children, child_org.id)
-- adding child to org list
modpol.orgs.array[child_org.id] = child_org
self:record('created sub org ' .. name, 'add_org')
modpol.ocutil.log('Created sub org ' .. name)
return child_org
end
-- ========================================
-- recursively deletes an org and its suborgs
-- leaves entry in modpol.orgs.array as a string "removed"
-- note: "reason" param was removed, can be added back
function modpol.orgs:delete()
if self.id == 1 then
modpol.ocutil.log('Error: cannot delete instance')
return false
end
if #self.children > 0 then
for i, child_id in pairs(self.children) do
local child = modpol.orgs.get_org(child_id)
print(child_id, child)
child:delete()
end
end
modpol.orgs.array[self.id] = 'removed'
modpol.ocutil.log('Removed ' .. self.name .. ': ' .. self.id)
self:record('Deleted ' .. self.name .. ' and all child orgs', 'del_org')
end
-- ===========================================
-- internal function to get the index of a member name
function modpol.orgs:get_member_index(member)
for k, v in ipairs(self.members) do
if v == member then
return k
end
end
end
-- ===========================================
-- adds a user to an org
function modpol.orgs:add_member(user)
-- trys to fill in empty spots first
local empty_index = self:get_member_index('')
if empty_index then
self.members[empty_index] = user
else
-- adds to end if no empty spots
table.insert(self.members, user)
end
self:record('Added member ' .. user, 'add_member')
end
-- =======================================
-- removes a user from an org
function modpol.orgs:remove_member(user)
-- sets the array index to an empty string so that consecutive list is preserved
-- empty spots will get filled in by new members
user_index = self:get_member_index(user)
if user_index then
self.members[user_index] = ''
end
self:record('Removed member ' .. user, 'del_member')
end
-- ===========================================
-- boolean check whether user is an org
function modpol.orgs:has_member(user)
user_index = self:get_member_index(user)
if user_index then
return true
else
return false
end
end
-- ==================================
-- returns a list of users in an org
function modpol.orgs:list_member()
local str
for k, v in ipairs(self.members) do
if str then
str = str .. '\n' .. v
else
str = v
end
end
return str
end
-- ====================================
-- adds a new policy to the policy table
-- must define the policy type, process associated with it, and whether the request must be made by an org member
function modpol.orgs:set_policy(policy_type, process, must_be_member)
local new_policy = {
process = process,
must_be_member = must_be_member
}
self.policies[policy_type] = policy
end
-- ================================
--
function modpol.orgs:create_process(request_id)
local new_process = {
object = "I am a process",
request_id = request_id
}
-- linear search for empty process slots (lazy deletion)
for k, v in ipairs(self.processes) do
if v == 'deleted' then
local empty_index = k
break
do
end
-- attempts to fill empty spots in list, otherwise appends to end
if empty_index then
self.processes[index] = new_process
else
table.insert(self.processes, new_process)
end
end
-- ===========================
-- compares to requests to see if they are identical
function modpol.orgs.comp_req(req1, req2)
-- compares request type
if req1.type ~= req2.type then
return false
else
-- comparing parameters
-- we can assume the number of params is the same as this is checked in the make_request func
for k, v in ipairs(req1.params) do
if v ~= req2.params[k] then
return false
end
end
end
return true
end
-- ================================
-- tries to make a request to the org
function modpol.orgs:make_request(request)
-- makes sure the request has the valid number of parameters
local num_params = modpol.orgs.request_params[request.type]
if num_params == nil then
modpol.ocutil.log("Error: request type is invalid")
return false
end
-- num_params should equal zero at the end if request.params matches the num of params for that type
for k, v in ipairs(request.params) do
num_params = num_params - 1
end
if num_params ~= 0 then
modpol.ocutil.log("Error: request has invalid number of parameters")
return false
end
-- checking to see if identical request already exists
for k, v in ipairs(self.requests) do
if self.comp_req(request, v) == true then
modpol.ocutil.log("Error: request has already been made")
return false
end
end
local requested_policy = self.policies[request.type]
if requested_policy then
end
-- use lazy deletion here, not very clean
-- table.insert(self.requests, request)
self.request_count = self.request_count + 1
self.requests[self.request_count] = request
return self.request_count
end