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 -- =========================== -- 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 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 -- 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